delphi 양방향 체인 테이블, 단방향 체인 테이블,Tlist 교체 가능, 삭제 효율 추가

10925 단어 Delphi
1. Tlist 삽입 삭제 메모리 작업이 너무 빈번하고 효율이 높지 않아 체인 테이블로 대체할 수 있다.
2. 다음 체인 테이블은 메모리 분배 빈도를 피하기 위해 Node 분배 탱크를 자체로 가지고 있다.
(단선 체인 테이블, 양방향 체인 테이블, 대기열 포함)
  
  //    
  pTSingleLinkedNode = ^TSingleLinkedNode;

  TSingleLinkedNode = record
  private
    Next: pTSingleLinkedNode;
  public
    Data: TObject;
  end;

  pTMyLinkedNode = ^TMyLinkedNode;

  TMyLinkedNode = record
  public
    Data: TObject;
  private
    Prev, Next: pTMyLinkedNode;
  end;


  //   
  TLinkedNodePool = class
  protected
    m_Nodes: array of Pointer;
    m_Index: Integer;
    m_Capacity: Integer;
    m_Stoped: Boolean;
    function NewNode: Pointer; virtual; abstract;
    procedure DisposeNode(p: Pointer); virtual; abstract;
  public
    constructor Create(nCapacity: Integer = 512); virtual;
    destructor Destroy; override;
    function GetNode: Pointer;
    procedure RetNode(p: Pointer);
    procedure ReSize;
    procedure Clear;
  end;

  //    
  TSingleLinkedBase = class(TLinkedNodePool)
  protected
    m_Head: pTSingleLinkedNode;
    m_Curr: pTSingleLinkedNode;
    m_Count: Integer;
    function NewNode: Pointer; override;
    procedure DisposeNode(p: Pointer); override;
    procedure AddObject(Obj: TObject);
    function DeleteObject(Obj: TObject): pTSingleLinkedNode;
  public
    constructor Create(nCapacity: Integer = 512); override;
    destructor Destroy; override;
    procedure Clear;
    function First: pTSingleLinkedNode;
    function Next: pTSingleLinkedNode;
    property Count: Integer read m_Count;
  end;

  //      
  TSingleObjectLinked = class(TSingleLinkedBase)
  public
    procedure Add(Obj: TObject);
    function Delete(Obj: TObject): pTSingleLinkedNode;
  end;

  //      
  TSinglePointerLinked = class(TSingleLinkedBase)
  public
    procedure Add(Ptr: Pointer);
    function Delete(Ptr: Pointer): pTSingleLinkedNode;
  end;

  //     ,        
  TMyLinkedBase = class(TLinkedNodePool)
  protected
    m_Head, m_Tail: pTMyLinkedNode;
    m_Curr: pTMyLinkedNode;
    m_Count: Integer;
    function NewNode: Pointer; override;
    procedure DisposeNode(p: Pointer); override;
    procedure AddObject(Obj: TObject);
    function DeleteObject(Obj: TObject): pTMyLinkedNode;
  public
    constructor Create(nCapacity: Integer = 512); override;
    destructor Destroy; override;
    function DeleteNode(var Node: pTMyLinkedNode): pTMyLinkedNode;
    function First: pTMyLinkedNode;
    function Next: pTMyLinkedNode;
    procedure Clear;
    property Count: Integer read m_Count;
  end;

  //      
  TMyObjectLinked = class(TMyLinkedBase)
  public
    procedure Add(Obj: TObject);
    function Delete(Obj: TObject): pTMyLinkedNode;
  end;

  //      
  TMyPointerLinked = class(TMyLinkedBase)
  public
    procedure Add(Ptr: Pointer);
    function Delete(Ptr: Pointer): pTMyLinkedNode;
  end;

  //  
  TMyQueueBase = class(TMyLinkedBase)
  protected
    procedure PushObject(Obj: TObject);
    function PopObject: TObject;
  end;

  //    
  TMyObjectQueue = class(TMyQueueBase)
  public
    procedure Push(Obj: TObject);
    function Pop: TObject;
  end;

  //    
  TMyPointerQueue = class(TMyQueueBase)
  public
    procedure Push(Ptr: Pointer);
    function Pop: Pointer;
  end;


{ TLinkedNodePool }

constructor TLinkedNodePool.Create(nCapacity: Integer);
begin
  SetLength(m_Nodes, nCapacity);
  m_Capacity := nCapacity;
  m_Index := -1;
end;

destructor TLinkedNodePool.Destroy;
begin
  m_Stoped := True;
  Clear;
  SetLength(m_Nodes, 0);
  inherited;
end;

procedure TLinkedNodePool.Clear;
var
  i: Integer;
begin
  for i := 0 to m_Index do
    DisposeNode(m_Nodes[i]);
end;

function TLinkedNodePool.GetNode: Pointer;
begin
  Result := nil;
  if m_Index < 0 then
    ReSize;

  if m_Index >= 0 then begin
    Result := m_Nodes[m_Index];
    Dec(m_Index);
  end;
end;

procedure TLinkedNodePool.RetNode(p: Pointer);
begin
  if (m_Index >= Length(m_Nodes) - 1) or m_Stoped then
    DisposeNode(p)
  else begin
    Inc(m_Index);
    m_Nodes[m_Index] := p;
  end;
end;

procedure TLinkedNodePool.ReSize;
var
  i: Integer;
  node: Pointer;
begin
  for i := 0 to (m_Capacity div 2) do begin
    if m_Index >= Length(m_Nodes) - 1 then
      m_Index := 0
    else
      Inc(m_Index);

    node := Self.NewNode;
    m_Nodes[m_Index] := node;
  end;
end;



{ TSingleLinkedBase }

var
  g_count: Integer;

constructor TSingleLinkedBase.Create(nCapacity: Integer);
begin
  inherited Create(nCapacity);
end;

destructor TSingleLinkedBase.Destroy;
begin
  Assert(g_count > 0);
  Clear;
  inherited;
  Assert(g_count = 0);
end;

procedure TSingleLinkedBase.Clear;
var
  Temp, Temp1: pTSingleLinkedNode;
begin
  Temp := m_Head;
  while Temp <> nil do begin
    Temp1 := Temp;
    Temp := Temp1.Next;
    Self.RetNode(Temp1);
  end;
  m_Head := nil;
  m_Count := 0;
end;

procedure TSingleLinkedBase.AddObject(Obj: TObject);
var
  node: pTSingleLinkedNode;
begin
  node := Self.GetNode;
  node.Data := Obj;
  node.Next := nil;
  if m_Head = nil then
    m_Head := node
  else begin
    node.Next := m_Head.Next;
    m_Head.Next := node;
  end;
  Inc(m_Count);
end;

function TSingleLinkedBase.DeleteObject(Obj: TObject): pTSingleLinkedNode;
var
  Temp, priNode: pTSingleLinkedNode;
begin
  Temp := m_head;
  priNode := nil;  //      
  Result := nil;
  while Temp <> nil do begin
    if Temp.Data = Obj then begin
      if priNode = nil then  //     
      begin
        m_Head := Temp.Next;
        m_Curr := Temp.Next; //     next  
        Result := Temp.Next;
        Self.RetNode(Temp);
        Dec(m_Count);
      end
      else begin
        priNode.Next := Temp.Next;   //      
        Result := Temp.Next;
        m_Curr := Temp.Next;
        Self.RetNode(Temp);
        Dec(m_Count);
      end;
      Break;
    end
    else begin
      priNode := Temp;
      Temp := Temp.Next;
    end;
  end;
end;

function TSingleLinkedBase.First: pTSingleLinkedNode;
begin
  m_Curr := m_Head;
  Result := m_Curr;
end;

function TSingleLinkedBase.Next: pTSingleLinkedNode;
begin
  m_Curr := m_Curr.Next;
  Result := m_Curr;
end;

procedure TSingleLinkedBase.DisposeNode(p: Pointer);
begin
  Dispose(pTSingleLinkedNode(p));
  Dec(g_count);
end;

function TSingleLinkedBase.NewNode: Pointer;
var
  node: pTSingleLinkedNode;
begin
  New(node);
  node.Data := nil;
  node.Next := nil;
  Result := node;
  Inc(g_count);
end;


{ TSingleObjectLinked }

procedure TSingleObjectLinked.Add(Obj: TObject);
begin
  inherited AddObject(Obj);
end;

function TSingleObjectLinked.Delete(Obj: TObject): pTSingleLinkedNode;
begin
  Result := inherited DeleteObject(Obj);
end;


{ TSinglePointerLinked }

procedure TSinglePointerLinked.Add(Ptr: Pointer);
begin
  inherited AddObject(TObject(Ptr));
end;

function TSinglePointerLinked.Delete(Ptr: Pointer): pTSingleLinkedNode;
begin
  Result := inherited DeleteObject(TObject(Ptr));
end;



{ TMyLinkedBase }

constructor TMyLinkedBase.Create(nCapacity: Integer);
begin
  inherited Create(nCapacity);
  New(m_Head);
  m_Head.Next := m_Tail;
  m_Head.Prev := nil;
  m_Head.Data := nil;
end;

destructor TMyLinkedBase.Destroy;
begin
  Dispose(m_Head);
  Clear;
  inherited;
end;

procedure TMyLinkedBase.AddObject(Obj: TObject);
var
  Node: pTMyLinkedNode;
begin
  Node := Self.GetNode;
  Node.Data := Obj;
  if m_Head.Next = nil then begin
    m_Head.Next := Node;
    Node.Prev := m_Head;
    Node.Next := nil;
    m_Tail := Node;
  end
  else begin
    m_Head.Next.Prev := Node;
    Node.Next := m_Head.Next;
    Node.Prev := m_Head;
    m_Head.Next := Node;
  end;
  Inc(m_Count);
end;

procedure TMyLinkedBase.Clear;
var
  Temp, Temp1: pTMyLinkedNode;
begin
  Temp := m_Head.Next;
  while Temp <> nil do begin
    Temp1 := Temp;
    Temp := Temp.Next;
    Self.RetNode(Temp1);
  end;
  m_Tail := nil;
  m_Head.Next := m_Tail;
  m_Count := 0;
end;


//   
function TMyLinkedBase.NewNode: Pointer;
var
  node: pTMyLinkedNode;
begin
  New(node);
  node.Data := nil;
  node.Prev := nil;
  node.Next := nil;
  Result := node;
end;

procedure TMyLinkedBase.DisposeNode(p: Pointer);
begin
  Dispose(pTMyLinkedNode(p));
end;

function TMyLinkedBase.First: pTMyLinkedNode;
begin
  m_Curr := m_Head.Next;
  Result := m_Curr;
end;

function TMyLinkedBase.Next: pTMyLinkedNode;
begin
  Result := m_Curr.Next;
  m_Curr := m_Curr.Next;
end;

function TMyLinkedBase.DeleteObject(Obj: TObject): pTMyLinkedNode;
var
  Temp: pTMyLinkedNode;
begin
  Temp := m_Head.Next;
  Result := nil;
  while Temp <> nil do begin
    if Temp.Data = Obj then begin
      Temp.Prev.Next := Temp.Next;
      Result := Temp.Next;
      m_Curr := Temp.Next;
      if Temp.Next <> nil then
        Temp.Next.Prev := Temp.Prev
      else if Temp.Prev = m_Head then
        m_Tail := nil
      else
        m_Tail := Temp.Prev;

      Self.RetNode(Temp);
      Dec(m_Count);
      Break;
    end
    else
      Temp := Temp.Next;
  end;
end;

function TMyLinkedBase.DeleteNode(var Node: pTMyLinkedNode): pTMyLinkedNode;
begin
  Result := Node.Next;
  m_Curr := Node.Next;
  Node.Prev.Next := Node.Next;
  if Node.Next <> nil then
    Node.Next.Prev := Node.Prev
  else if Node.Prev = m_Head then
    m_Tail := nil
  else
    m_Tail := Node.Prev;

  Self.RetNode(Node);
  Dec(m_Count);
end;


{ TMyObjectLinked }

procedure TMyObjectLinked.Add(Obj: TObject);
begin
  inherited AddOBject(Obj);
end;

function TMyObjectLinked.Delete(Obj: TObject): pTMyLinkedNode;
begin
  Result := inherited DeleteObject(Obj);
end;


{ TMyPointerLinked }

procedure TMyPointerLinked.Add(Ptr: Pointer);
begin
  inherited AddObject(TObject(Ptr));
end;

function TMyPointerLinked.Delete(Ptr: Pointer): pTMyLinkedNode;
begin
  Result := inherited DeleteObject(TObject(Ptr));
end;


{ TMyQueueBase }

function TMyQueueBase.PopObject: TObject;
var
  Temp: pTMyLinkedNode;
begin
  Temp := m_Head.Next;
  Result := nil;
  if Temp <> nil then begin
    Result := Temp.Data;
    m_Head.Next := Temp.Next;
    Temp.Prev := m_Head;
    if m_Head.Next = nil then
      m_Tail := nil;
    Self.RetNode(Temp);
    m_Curr := m_Head.Next; //     
  end;
  Dec(m_Count);
end;

procedure TMyQueueBase.PushObject(Obj: TObject);
var
  Node: pTMyLinkedNode;
begin
  Node := GetNode;
  Node.Data := Obj;
  if m_Tail = nil then begin
    m_Tail := Node;
    m_Tail.Next := nil;
    m_Tail.Prev := m_Head;
    m_Head.Next := m_Tail;
  end
  else begin
    m_Tail.Next := Node;
    Node.Prev := m_Tail;
    Node.Next := nil;
    m_Tail := Node;
  end;
  Inc(m_Count);
end;

{ TMyObjectQueue }

function TMyObjectQueue.Pop: TObject;
begin
  Result := inherited PopObject;
end;

procedure TMyObjectQueue.Push(Obj: TObject);
begin
  inherited PushObject(Obj);
end;

{ TMyPointerQueue }

function TMyPointerQueue.Pop: Pointer;
begin
  Result := Pointer(inherited PopObject);
end;

procedure TMyPointerQueue.Push(Ptr: Pointer);
begin
  inherited PushObject(TObject(Ptr));
end;

좋은 웹페이지 즐겨찾기