📄 jclbinarytrees.pas
字号:
{**************************************************************************************************}
{ }
{ Project JEDI Code Library (JCL) }
{ }
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
{ License at http://www.mozilla.org/MPL/ }
{ }
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
{ and limitations under the License. }
{ }
{ The Original Code is BinaryTree.pas. }
{ }
{ The Initial Developer of the Original Code is Jean-Philippe BEMPEL aka RDM. Portions created by }
{ Jean-Philippe BEMPEL are Copyright (C) Jean-Philippe BEMPEL (rdm_30 att yahoo dott com) }
{ All rights reserved. }
{ }
{**************************************************************************************************}
{ }
{ The Delphi Container Library }
{ }
{**************************************************************************************************}
// Last modified: $Date: 2005/03/08 08:33:15 $
// For history see end of file
unit JclBinaryTrees;
{$I jcl.inc}
{.DEFINE RECURSIVE}
interface
uses
Classes,
JclBase, JclAbstractContainers, JclAlgorithms, JclContainerIntf;
type
TJclTreeColor = (tcBlack, tcRed);
PJclIntfBinaryNode = ^TJclIntfBinaryNode;
TJclIntfBinaryNode = record
Obj: IInterface;
Left: PJclIntfBinaryNode;
Right: PJclIntfBinaryNode;
Parent: PJclIntfBinaryNode;
Color: TJclTreeColor;
end;
PJclStrBinaryNode = ^TJclStrBinaryNode;
TJclStrBinaryNode = record
Str: string;
Left: PJclStrBinaryNode;
Right: PJclStrBinaryNode;
Parent: PJclStrBinaryNode;
Color: TJclTreeColor;
end;
PJclBinaryNode = ^TJclBinaryNode;
TJclBinaryNode = record
Obj: TObject;
Left: PJclBinaryNode;
Right: PJclBinaryNode;
Parent: PJclBinaryNode;
Color: TJclTreeColor;
end;
TJclIntfBinaryTree = class(TJclAbstractContainer, IJclIntfCollection,
IJclIntfTree, IJclIntfCloneable)
private
FComparator: TIntfCompare;
FCount: Integer;
FRoot: PJclIntfBinaryNode;
FTraverseOrder: TJclTraverseOrder;
procedure RotateLeft(Node: PJclIntfBinaryNode);
procedure RotateRight(Node: PJclIntfBinaryNode);
protected
{ IJclIntfCollection }
function Add(AInterface: IInterface): Boolean;
function AddAll(ACollection: IJclIntfCollection): Boolean;
procedure Clear;
function Contains(AInterface: IInterface): Boolean;
function ContainsAll(ACollection: IJclIntfCollection): Boolean;
function Equals(ACollection: IJclIntfCollection): Boolean;
function First: IJclIntfIterator;
function IsEmpty: Boolean;
function Last: IJclIntfIterator;
function Remove(AInterface: IInterface): Boolean;
function RemoveAll(ACollection: IJclIntfCollection): Boolean;
function RetainAll(ACollection: IJclIntfCollection): Boolean;
function Size: Integer;
{ IJclIntfTree }
function GetTraverseOrder: TJclTraverseOrder;
procedure SetTraverseOrder(Value: TJclTraverseOrder);
{ IJclIntfCloneable }
function Clone: IInterface;
public
constructor Create(AComparator: TIntfCompare = nil);
destructor Destroy; override;
end;
{
TJclStrBinaryTree = class(TJclAbstractContainer, IJclStrCollection,
IJclStrTree, IJclCloneable)
}
TJclStrBinaryTree = class(TJclStrCollection, IJclStrTree, IJclCloneable)
private
FComparator: TStrCompare;
FCount: Integer;
FRoot: PJclStrBinaryNode;
FTraverseOrder: TJclTraverseOrder;
procedure RotateLeft(Node: PJclStrBinaryNode);
procedure RotateRight(Node: PJclStrBinaryNode);
protected
{ IJclStrCollection }
function Add(const AString: string): Boolean; override;
function AddAll(ACollection: IJclStrCollection): Boolean; override;
procedure Clear; override;
function Contains(const AString: string): Boolean; override;
function ContainsAll(ACollection: IJclStrCollection): Boolean; override;
function Equals(ACollection: IJclStrCollection): Boolean; override;
function First: IJclStrIterator; override;
function IsEmpty: Boolean; override;
function Last: IJclStrIterator; override;
function Remove(const AString: string): Boolean; override;
function RemoveAll(ACollection: IJclStrCollection): Boolean; override;
function RetainAll(ACollection: IJclStrCollection): Boolean; override;
function Size: Integer; override;
{ IJclStrTree }
function GetTraverseOrder: TJclTraverseOrder;
procedure SetTraverseOrder(Value: TJclTraverseOrder);
{ IJclCloneable }
function Clone: TObject;
public
constructor Create(AComparator: TStrCompare = nil);
destructor Destroy; override;
end;
TJclBinaryTree = class(TJclAbstractContainer, IJclCollection, IJclTree,
IJclCloneable)
private
FComparator: TCompare;
FCount: Integer;
FRoot: PJclBinaryNode;
FTraverseOrder: TJclTraverseOrder;
procedure RotateLeft(Node: PJclBinaryNode);
procedure RotateRight(Node: PJclBinaryNode);
protected
{ IJclCollection }
function Add(AObject: TObject): Boolean;
function AddAll(ACollection: IJclCollection): Boolean;
procedure Clear;
function Contains(AObject: TObject): Boolean;
function ContainsAll(ACollection: IJclCollection): Boolean;
function Equals(ACollection: IJclCollection): Boolean;
function First: IJclIterator;
function IsEmpty: Boolean;
function Last: IJclIterator;
function Remove(AObject: TObject): Boolean;
function RemoveAll(ACollection: IJclCollection): Boolean;
function RetainAll(ACollection: IJclCollection): Boolean;
function Size: Integer;
{ IJclTree }
function GetTraverseOrder: TJclTraverseOrder;
procedure SetTraverseOrder(Value: TJclTraverseOrder);
{ IJclCloneable }
function Clone: TObject;
public
constructor Create(AComparator: TCompare = nil);
destructor Destroy; override;
end;
implementation
uses
SysUtils,
JclResources;
//=== { TIntfItr } ===========================================================
type
TIntfItr = class(TJclAbstractContainer, IJclIntfIterator)
private
FCursor: PJclIntfBinaryNode;
FOwnList: TJclIntfBinaryTree;
FLastRet: PJclIntfBinaryNode;
protected
{ IJclIntfIterator }
procedure Add(AInterface: IInterface);
function GetObject: IInterface;
function HasNext: Boolean;
function HasPrevious: Boolean;
function Next: IInterface; virtual;
function NextIndex: Integer;
function Previous: IInterface; virtual;
function PreviousIndex: Integer;
procedure Remove;
procedure SetObject(AInterface: IInterface);
public
constructor Create(OwnList: TJclIntfBinaryTree; Start: PJclIntfBinaryNode);
destructor Destroy; override;
end;
constructor TIntfItr.Create(OwnList: TJclIntfBinaryTree; Start: PJclIntfBinaryNode);
begin
inherited Create;
FCursor := Start;
FOwnList := OwnList;
FOwnList._AddRef; // Add a ref because FOwnList is not an interface !
FLastRet := nil;
end;
destructor TIntfItr.Destroy;
begin
FOwnList._Release;
inherited Destroy;
end;
procedure TIntfItr.Add(AInterface: IInterface);
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
FOwnList.Add(AInterface);
end;
function TIntfItr.GetObject: IInterface;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := FCursor.Obj;
end;
function TIntfItr.HasNext: Boolean;
begin
Result := FCursor <> nil;
end;
function TIntfItr.HasPrevious: Boolean;
begin
Result := FCursor <> nil;
end;
function TIntfItr.Next: IInterface;
begin
end;
function TIntfItr.NextIndex: Integer;
begin
// No index
raise EJclOperationNotSupportedError.CreateRes(@RsEOperationNotSupported);
end;
function TIntfItr.Previous: IInterface;
begin
end;
function TIntfItr.PreviousIndex: Integer;
begin
// No index
raise EJclOperationNotSupportedError.CreateRes(@RsEOperationNotSupported);
end;
procedure TIntfItr.Remove;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
FOwnList.Remove(Next);
end;
procedure TIntfItr.SetObject(AInterface: IInterface);
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
FCursor.Obj := AInterface;
end;
//=== { TPreOrderIntfItr } ===================================================
type
TPreOrderIntfItr = class(TIntfItr, IJclIntfIterator)
protected
{ IJclIntfIterator }
function Next: IInterface; override;
function Previous: IInterface; override;
end;
function TPreOrderIntfItr.Next: IInterface;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := FCursor.Obj;
FLastRet := FCursor;
if FCursor.Left <> nil then
FCursor := FCursor.Left
else
if FCursor.Right <> nil then
FCursor := FCursor.Right
else
begin
FCursor := FCursor.Parent;
while (FCursor <> nil) and (FCursor.Left <> FLastRet) do // come from Right
begin
FLastRet := FCursor;
FCursor := FCursor.Parent;
end;
while (FCursor <> nil) and (FCursor.Right = nil) do
begin
FLastRet := FCursor;
FCursor := FCursor.Parent;
end;
if FCursor <> nil then // not root
FCursor := FCursor.Right;
end;
end;
function TPreOrderIntfItr.Previous: IInterface;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := FCursor.Obj;
FLastRet := FCursor;
FCursor := FCursor.Parent;
if (FCursor <> nil) and (FCursor.Left <> FLastRet) then // come from Right
if FCursor.Left <> nil then
begin
FLastRet := FCursor;
FCursor := FCursor.Left;
while FCursor.Right <> nil do
begin
FLastRet := FCursor;
FCursor := FCursor.Right;
end;
end;
end;
//=== { TInOrderIntfItr } ====================================================
type
TInOrderIntfItr = class(TIntfItr, IJclIntfIterator)
protected
{ IJclIntfIterator }
function Next: IInterface; override;
function Previous: IInterface; override;
end;
function TInOrderIntfItr.Next: IInterface;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
if FCursor.Left <> FLastRet then
while FCursor.Left <> nil do
FCursor := FCursor.Left;
Result := FCursor.Obj;
FLastRet := FCursor;
if FCursor.Right <> nil then
FCursor := FCursor.Right
else
begin
FCursor := FCursor.Parent;
while (FCursor <> nil) and (FCursor.Right = FLastRet) do
begin
FLastRet := FCursor;
FCursor := FCursor.Parent;
end;
end;
end;
function TInOrderIntfItr.Previous: IInterface;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := FCursor.Obj;
FLastRet := FCursor;
if FCursor.Left <> nil then
begin
FCursor := FCursor.Left;
while FCursor.Right <> nil do
begin
FLastRet := FCursor;
FCursor := FCursor.Right;
end;
end
else
begin
FCursor := FCursor.Parent;
while (FCursor <> nil) and (FCursor.Right <> FLastRet) do // Come from Left
begin
FLastRet := FCursor;
FCursor := FCursor.Parent;
end;
end;
end;
//=== { TPostOrderIntfItr } ==================================================
type
TPostOrderIntfItr = class(TIntfItr, IJclIntfIterator)
protected
{ IJclIntfIterator }
function Next: IInterface; override;
function Previous: IInterface; override;
end;
function TPostOrderIntfItr.Next: IInterface;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
if (FCursor.Left <> FLastRet) and (FCursor.Right <> FLastRet) then
while FCursor.Left <> nil do
FCursor := FCursor.Left;
if (FCursor.Right <> nil) and (FCursor.Right <> FLastRet) then
begin
FCursor := FCursor.Right;
while FCursor.Left <> nil do
FCursor := FCursor.Left;
if FCursor.Right <> nil then // particular worst case
FCursor := FCursor.Right;
end;
Result := FCursor.Obj;
FLastRet := FCursor;
FCursor := FCursor.Parent;
end;
function TPostOrderIntfItr.Previous: IInterface;
{$IFDEF THREADSAFE}
var
CS: IInterface;
{$ENDIF THREADSAFE}
begin
{$IFDEF THREADSAFE}
CS := EnterCriticalSection;
{$ENDIF THREADSAFE}
Result := FCursor.Obj;
FLastRet := FCursor;
if (FCursor.Right <> nil) and (FCursor.Right <> FLastRet) then
FCursor := FCursor.Right
else
begin
FCursor := FCursor.Parent;
while (FCursor <> nil) and ((FCursor.Left = nil) or (FCursor.Left = FLastRet)) do
begin
FLastRet := FCursor;
FCursor := FCursor.Parent;
end;
if FCursor <> nil then // not root
FCursor := FCursor.Left;
end;
end;
//=== { TStrItr } ============================================================
type
TStrItr = class(TJclAbstractContainer, IJclStrIterator)
protected
FCursor: PJclStrBinaryNode;
FOwnList: TJclStrBinaryTree;
FLastRet: PJclStrBinaryNode;
{ IJclStrIterator }
procedure Add(const AString: string);
function GetString: string;
function HasNext: Boolean;
function HasPrevious: Boolean;
function Next: string; virtual;
function NextIndex: Integer;
function Previous: string; virtual;
function PreviousIndex: Integer;
procedure Remove;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -