⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deque.inc_pas

📁 Delphi Generic Algorytms library - Maps, Lists, Hashmaps, Datastructures.
💻 INC_PAS
📖 第 1 页 / 共 3 页
字号:
(*
 * DGL(The Delphi Generic Library)
 *
 * Copyright (c) 2004
 * HouSisong@263.net
 *
 * This material is provided "as is", with absolutely no warranty expressed
 * or implied. Any use is at your own risk.
 *
 * Permission to use or copy this software for any purpose is hereby granted
 * without fee, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 *
 *)

//------------------------------------------------------------------------------
// _TDeque的实现
// Create by HouSisong, 2004.09.02
//------------------------------------------------------------------------------

{$ifndef  __Deque_inc_pas_}
{$define  __Deque_inc_pas_}              
//Deque.inc_h , Deque.inc_pas

{$I DGLIntf.inc_pas}


{ _TDeque }
const
  csDeultCapability =8;
  
{$ifdef _DGL_ClassFunction_Specific}  //if TValueType=TNotifyEvent then do;
    function _TDeque_Get_ClassFunction_Address(var Value):_PValueType;  {$ifdef _DGL_Inline} inline; {$endif}
    begin
      result:=@Value;
    end;
{$endif}

function  _TDeque.GetSelfObj():TObject;
begin
  result:=self;
end;

function  _TDeque.IsEmpty(): Boolean;
begin
  result:=(self.FFrontPos.PCurValue=self.FEndPos.PCurValue);
end;


function _TDeque.GetBackValue: _ValueType;
var
  PValue : _PValueType;
  FBackPos : _TDequePos;
begin
  Assert(self.FFrontPos.PCurValue<>self.FEndPos.PCurValue);
  PValue:=FEndPos.PCurValue;
  if Pointer(PValue)=Pointer(FEndPos.PPNode^) then
  begin
    FBackPos:=FEndPos;
    _TDeque_DecPos(FBackPos);
    PValue:=FBackPos.PCurValue;
  end
  else
    Dec(PValue);
  result:=PValue^;
end;

procedure _TDeque.SetBackValue(const aValue:_ValueType);
var
  PValue : _PValueType;
  FBackPos : _TDequePos;
begin
  Assert(self.FFrontPos.PCurValue<>self.FEndPos.PCurValue);
  PValue:=FEndPos.PCurValue;
  if Pointer(PValue)=Pointer(FEndPos.PPNode^) then
  begin
    FBackPos:=FEndPos;
    _TDeque_DecPos(FBackPos);
    PValue:=FBackPos.PCurValue;
  end
  else
    Dec(PValue);

  {$ifdef _DGL_ObjValue}
    _Assign(PValue^,aValue);
  {$else}
    PValue^:=aValue;
  {$endif}
end;

{$ifdef  _DGL_ObjValue}
procedure _Deque_Free_ObjValue(ADeque:_TDeque;PBegin,PEnd:_TDequePos);
var
  PValue : _PValueType;
begin
  while (PBegin.PCurValue<>PEnd.PCurValue) do
  begin
    PValue:=(PBegin.PCurValue);
    _Free(PValue^);
    PValue^:=_Null_Value;
    _TDeque_IncPos(PBegin);
  end;
end;
{$endif}

procedure _TDeque.DestroyClear();
var
  i : integer;      
begin
  {$ifdef  _DGL_ObjValue}
    _Deque_Free_ObjValue(self,FFrontPos,FEndPos);
  {$endif}
  for i:=low(FNodeArray) to high(FNodeArray) do
    self.DeleteNode(FNodeArray[i]);
  FNodeArray:=nil;
  self.FFrontPos.PPNode:=nil;
  self.FFrontPos.PCurValue:=nil;
  self.FFrontPos.PEndValue:=nil;
  self.FEndPos.PPNode:=nil;
  self.FEndPos.PCurValue:=nil;
  self.FEndPos.PEndValue:=nil;
end;

procedure _TDeque.Clear;
begin
  DestroyClear();
  setlength(FNodeArray,csDeultCapability);
  self.FFrontPos.PPNode:=@FNodeArray[csDeultCapability shr 1];
  self.FEndPos.PPNode:=self.FFrontPos.PPNode;
end;

procedure _TDeque.Swap(ADeque:_TDeque);
var
  tmpNodeArray  : _TPDequeNodeDArray;
  tmpPos  : _TDequePos;
begin
  if self=ADeque then exit;
  
  tmpNodeArray:=FNodeArray;  FNodeArray:=ADeque.FNodeArray;  ADeque.FNodeArray:=tmpNodeArray;
  tmpPos:=FFrontPos;  FFrontPos:=ADeque.FFrontPos;  ADeque.FFrontPos:=tmpPos;
  tmpPos:=FEndPos;  FEndPos:=ADeque.FEndPos;  ADeque.FEndPos:=tmpPos;
end;



constructor _TDeque.Create(const num: integer; const Value: _ValueType);
begin
  inherited Create();
  Clear();
  self.PushBack(num,Value);
end;

constructor _TDeque.Create(const num: integer);
{$ifdef  _DGL_ObjValue}
var
  _Default_Value : _ValueType;
{$endif}
begin
  inherited Create();
  Clear();
  {$ifdef  _DGL_ObjValue}
    _Default_Value:=_CreateNew();
    self.PushBack(num,_Default_Value);
    _Free(_Default_Value);
  {$else}
    self.PushBack(num,_NULL_Value);
  {$endif}
end;

constructor _TDeque.Create;
begin
  inherited;
  Clear();
end;

procedure _TDeque.Copy(PBegin, PEnd, PDest: _TDequePos);
begin
  while (PBegin.PCurValue<>PEnd.PCurValue) do
  begin
    {$ifdef  _DGL_ObjValue}
      _Assign((PDest.PCurValue)^,(PBegin.PCurValue)^);
    {$else}
      (PDest.PCurValue)^:=(PBegin.PCurValue)^;
    {$endif}
    _TDeque_IncPos(PBegin);
    _TDeque_IncPos(PDest);
  end;
end;

constructor _TDeque.Create(const ADeque: _TDeque);
begin
  inherited Create();
  Clear();
  self.PushBack(ADeque.ItBegin,ADeque.ItEnd);
end;

constructor _TDeque.Create(const ItBegin, ItEnd: _IIterator);
begin
  inherited Create();
  Clear();
  self.PushBack(ItBegin, ItEnd);
end;

procedure _TDeque.Resize(const num: integer; const Value: _ValueType);
var
  i : integer;
  OldCount : integer;
begin
  OldCount:=_TDeque_Distance(FFrontPos,FEndPos);
  if num<OldCount then
  begin
    for i:=num to OldCount-1 do
      PopBack();
  end
  else
  begin
    for i:=OldCount to num-1 do
      PushBack(Value);
  end;
end;

procedure _TDeque.Resize(const num:integer);
{$ifdef  _DGL_ObjValue}
var
  _Default_Value : _ValueType;
{$endif}
begin
  {$ifdef  _DGL_ObjValue}
    _Default_Value:=_CreateNew();
    self.Resize(num,_Default_Value);
    _Free(_Default_Value);
  {$else}
    self.Resize(num,_NULL_Value);
  {$endif}
end;

procedure _TDeque.EraseByIndex(const Index: integer);
begin
  Erase(NewIterator(Index));
end;

procedure _TDeque.InsertByIndex(const Index: Integer;const Value: _ValueType);
begin
  Insert(NewIterator(Index),Value);
end;

class procedure _TDeque.DeleteNode(var pNode: _PDequeNode);
begin
  if pNode<>nil then
  begin
    system.Dispose(_PMemDequeNode(pNode));
    pNode:=nil;
  end;
end;

destructor _TDeque.Destroy;
begin
  self.DestroyClear();
  inherited;
end;

procedure _TDeque.Erase(const ItBegin, ItEnd: _IIterator);
var
  Index: integer;
  BeginPos,EndPos,DestPos : _TDequePos;
  num:integer;
  i : integer;
  EndIndex : integer;
  OldCount : integer;
begin
  Index:=_TDeque_Distance(self.FFrontPos,_PDequeIt(@ItBegin).Pos);
  EndIndex:=_TDeque_Distance(self.FFrontPos,_PDequeIt(@ItEnd).Pos);
  num:=ItBegin.Distance(ItEnd);
  if num<=0 then exit;

  OldCount:=_TDeque_Distance(FFrontPos,FEndPos);
  if Index=0 then
  begin
    for i:=0 to num-1 do self.PopFront();
  end
  else if (EndIndex)=OldCount then
  begin
    for i:=0 to num-1 do self.PopBack();
  end
  else
  begin
    if Index+(num  div 2)>=OldCount div 2 then
    begin
      DestPos:=self.GetPos(Index);
      BeginPos:=DestPos;
      _TDeque_IncPos(BeginPos,num);
      self.Copy(BeginPos,FEndPos,DestPos);
      for i:=0 to num-1 do self.PopBack();
    end
    else
    begin
      EndPos:=self.GetPos(Index);
      DestPos:= self.FFrontPos;
      _TDeque_IncPos(DestPos,num);
      self.ReCopy(FFrontPos,EndPos,DestPos);
      for i:=0 to num-1 do self.PopFront();
    end;
  end;
end;

procedure _TDeque.Erase(const ItPos: _IIterator);
var
  ItEnd : _IIterator;
begin
  ItEnd:=ItPos.Clone;
  ItEnd.Next;
  Erase(ItPos,ItEnd);
end;

procedure _TDeque.Fill(PBegin, PEnd: _TDequePos; const Value: _ValueType);
begin
  while (PBegin.PCurValue<>PEnd.PCurValue) do
  begin
    {$ifdef  _DGL_ObjValue}
    _Assign((PBegin.PCurValue)^,Value);
    {$else}
    (PBegin.PCurValue)^:=Value;
    {$endif}
    _TDeque_IncPos(PBegin);
  end;
end;

function _TDeque.ItBegin: _IIterator;
begin
  _TDequeIterator.ItCreate(result,FFrontPos);
end;

function  _TDeque.NewIterator(const Index: Integer):_IIterator;
begin
  _TDequeIterator.ItCreate(result,self,Index);
end;

function _TDeque.GetFrontValue: _ValueType;
begin
  Assert(self.FFrontPos.PCurValue<>self.FEndPos.PCurValue);
  result:=(FFrontPos.PCurValue)^;
end;

procedure _TDeque.SetFrontValue(const aValue:_ValueType);
begin
  Assert(self.FFrontPos.PCurValue<>self.FEndPos.PCurValue);
  {$ifdef _DGL_ObjValue}
    _Assign((FFrontPos.PCurValue)^,aValue);
  {$else}
    (FFrontPos.PCurValue)^:=aValue;
  {$endif}
end;

function _TDeque.GetItemValue(const Index: Integer): _ValueType;
begin
  Assert(Index>=0);
  Assert(Index<_TDeque_Distance(FFrontPos,FEndPos));
  result:=self.GetAItemAddress(Index)^;
end;

function _TDeque.GetPos(const Index: integer): _TDequePos;
begin
  result:=FFrontPos;
  _TDeque_IncPos(result,Index);
end;

function _TDeque.GetAItemAddress(const ItemIndex:integer): _PValueType;
var
  ValueIndex,NodeCount:integer;
  ppNode : _PPDequeNode;
begin
  ValueIndex:=ItemIndex+(csDequeNodeCount) + (integer(FFrontPos.PCurValue)-integer(FFrontPos.PEndValue)) div (sizeof(_ValueType));
  NodeCount:=ValueIndex div csDequeNodeCount;
  ppNode:=_PPDequeNode(integer(FFrontPos.PPNode)+NodeCount*sizeof(_PPDequeNode));
  ValueIndex:=ValueIndex-NodeCount*csDequeNodeCount;
  result:={$ifdef _DGL_ClassFunction_Specific}_TDeque_Get_ClassFunction_Address{$else}@{$endif}(ppNode^[ValueIndex]);
end;

function _TDeque.IndexOf(const Value: _ValueType): Integer;
var
  i : integer;
  Pos : _TDequePos;
  OldCount : integer;
begin
  Pos:=self.FFrontPos;
  OldCount:=_TDeque_Distance(FFrontPos,FEndPos);
  for i:=0 to OldCount-1 do
  begin
    {$ifdef  _DGL_Compare}
      if (_IsEqual(Value,(Pos.PCurValue)^)) then
    {$else}
      if Value=(Pos.PCurValue)^ then
    {$endif}
    begin
      result:=i;
      exit;
    end;
    _TDeque_IncPos(Pos);
  end;
  result:=-1;
end;

procedure _TDeque.Insert(const ItPos: _IIterator; const Value: _ValueType);
var
  Index: integer;
begin
  Index:=_TDeque_Distance(self.FFrontPos,_PDequeIt(@ItPos).Pos);
  if Index=0 then
    self.PushFront(Value)
  else if (Index>=_TDeque_Distance(FFrontPos,FEndPos)) then
    self.PushBack(Value)
  else
    Insert(ItPos,1,Value);
end;

procedure _TDeque.Insert(const Value:_ValueType);
begin
  self.PushBack(Value);
end;

procedure _TDeque.Insert(const ItPos: _IIterator; const num: integer;
  const Value: _ValueType);
var
  Index: integer;
begin
  if num<=0 then exit;
  
  Index:=_TDeque_Distance(self.FFrontPos,_PDequeIt(@ItPos).Pos);
  if Index=0 then
    self.PushFront(num,Value)
  else if (Index>=_TDeque_Distance(FFrontPos,FEndPos)) then
    self.PushBack(num,Value)
  else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -