怎么构造一个 IntegerList 类?(100分)

  • 主题发起人 主题发起人 乖乖兔
  • 开始时间 开始时间

乖乖兔

Unregistered / Unconfirmed
GUEST, unregistred user!
Delphi 中默认有 TStringList 和 TStrings 类,
现在我想自义一个 TIntergerList 用来维护一个整数列表,请各位给我些思路。
其中也要有 Items,Add,Delete,等函数,
虽然用 TList 也可以达到目的,但有进行一个指针类的转换,有点烦,不想用!
 
我做过类似的类,直接使用就是了,也是仿照TStringsList做的, TIntList就是你所要的,TPointList是TPoint列表类。.

unit ExtList;

interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, Mask, Math, ExtCtrls, Menus, Base;
const
MaxListLen = Maxint div 16;
type
TCompareResult=(crSame,crLarge,crSmall);
PPointArr = ^TPointArr;
TPointArr = array[0..MaxListLen - 1] of TPoint;

PIntArr = ^TIntArr;
TIntArr = array[0..MaxListLen - 1] of Integer;

TIntList = class(TPersistent)
private
FList: PIntArr
//数组指针
FCount: Integer
//实际项目个数
FCapacity: Integer
//库容量
protected
function Get(Index: Integer): Integer;
procedure Put(Index: Integer
Item: Integer);
procedure SetCount(NewCount: Integer);
procedure Grow
virtual;
procedure SetCapacity(NewCapacity: Integer);
public
destructor Destroy
override;
function Add(Item: Integer): Integer;
procedure Clear
virtual;
procedure Delete(Index: Integer);
function IndexOf(Item: Integer): Integer;
function IndexOfAfter(After,Item: Integer): Integer;
function CountOfItem(Item: Integer): Integer
//值为Item的个数
function Max: Integer
//求最大值
procedure Insert(Index: Integer
Item: Integer);
function Remove(Item: Integer): Integer;
property Count: Integer read FCount write SetCount;
property Items[Index: Integer]: Integer read Get write Put
default;
property Capacity: Integer read FCapacity write SetCapacity;
procedure LoadFromStream(Stream: TStream);
procedure SaveToStream(Stream: TStream);
procedure AssignTo(Dest: TPersistent)
override;
procedure Assign(Source: TPersistent)
override;
function SumBefore(BeforeIndex:Integer):Integer;
function Sum(IndexArr:array of Integer):Integer;
function SumAll:Integer;
procedure Sort(araising:Boolean );
procedure Reset(Value:Integer );
procedure Exchange(Index1, Index2: Integer)

constructor Create;
end;

TPointList = class(TPersistent)
private
FList: PPointArr
//数组指针
FCount: Integer
//实际项目个数
FCapacity: Integer
//库容量
function IsSame(Index1,Index2:Integer): Boolean;overload;//比较两个Item
function IsSame(Item1,Item2: TPoint): Boolean;overload;//比较两个Item
protected
function Get(Index: Integer): TPoint;
procedure Put(Index: Integer
Item: TPoint);
procedure SetCount(NewCount: Integer);
procedure Grow
virtual;
procedure SetCapacity(NewCapacity: Integer);
public
destructor Destroy
override;
function Add(Item: TPoint): Integer;
procedure Clear
virtual;
procedure Delete(Index: Integer);
function IndexOf(Item: TPoint): Integer;
procedure Insert(Index:Integer
Item: TPoint);
function Remove(Item: TPoint): Integer;
property Count: Integer read FCount write SetCount;
property Items[Index: Integer]: TPoint read Get write Put
default;
property Capacity: Integer read FCapacity write SetCapacity;
procedure LoadFromStream(Stream: TStream);
procedure SaveToStream(Stream: TStream);
procedure AssignTo(Dest: TPersistent)
override;
procedure Assign(Source: TPersistent)
override;
constructor Create

end;

function SortIndexOfIntObj(aIntObj:TIntList):TIntList
//(13,12,17,13,16,19)权数=>排名(3,5,1,4,2,0)

implementation
////////////////////////////////////////////////////////////////////////////////////
function SortIndexOfIntObj(aIntObj:TIntList):TIntList
//(13,12,17,13,16,19)权数=>排名(3,5,1,4,2,0)
var aCount,aPos,i,j,aValue,Index,AfterPos:Integer;
aValueObj,aCountObj,aTmpObj:TIntList;
begin//Result.Item=aIntObj.Item值的排名 (13,12,17,13,16,19)=>(3,5,1,4,2,0) 13=0位权数=>0位排名
Result:=TIntList.Create;
Result.Count:=aIntObj.Count;
Result.Reset(0);
aValueObj:=TIntList.Create;
aCountObj:=TIntList.Create;
aTmpObj:=TIntList.Create;
aTmpObj.Assign(aIntObj);
while (aTmpObj.Count>0) do begin
aValue:=aTmpObj.Max;
aCount:=aTmpObj.CountOfItem(aValue);
aCountObj.Add(aCount);
aValueObj.Add(aValue);
for i :=0 to aCount-1 do begin
Index:=aTmpObj.IndexOf(aValue);
aTmpObj.Delete(Index);//(13,12,17,13,16,19)权数
end;//=>aCountObj(1,1,1,1,2,1)权数的个数
end
//=>aValueObj(19,17,16,13,12)权数值排列
Index:=0;
for i :=0 to aValueObj.Count-1 do begin
aValue:=aValueObj.Items;
AfterPos:=0;
for j :=0 to aCountObj.Items-1 do begin
aPos:=aIntObj.IndexOfAfter(AfterPos,aValue)
//aValue=19,aPos=5
AfterPos:=aPos+1;
Result.Items[aPos]:=Index
//=>排名Index(3,5,1,4,2,0)
Inc(Index);
end;
end;
aTmpObj.Free;
aValueObj.Free;
aCountObj.Free;
end;
////////////////////////////////////////////////////////////////////////////////////

procedure TIntList.Assign(Source: TPersistent);
var i,Len:Integer;
aLst:TIntList;
begin
if not (Source is TIntList) then
raise Exception.Create('TIntList.Assign Source isnot valid!');
aLst:=(Source as TIntList);
Clear

Len:=aLst.Count;
SetCount(Len);
for i :=0 to Len-1 do begin
Items:=aLst.Items;
end;
end;

procedure TIntList.AssignTo(Dest: TPersistent);
begin
if not (Dest is TIntList) then
raise Exception.Create('TIntList.AssignTo Dest isnot valid!');
(Dest as TIntList).Assign(Self);
end;
destructor TIntList.Destroy;
begin
Clear;
end;

function TIntList.Add(Item: Integer): Integer;
begin
Result := FCount;
if Result = FCapacity then
Grow;
FList^[Result] := Item;
Inc(FCount);
end;

procedure TIntList.Clear;
begin
SetCount(0);
SetCapacity(0);
end;

constructor TIntList.Create;
begin
inherited;
inherited;
FCount:=0;
FCapacity:=0;
FList:=nil;
end;

procedure TIntList.Delete(Index: Integer);
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.Create('TIntList.Delete Index isnot valid!');
Dec(FCount);
if Index < FCount then
System.Move(FList^[Index + 1], FList^[Index],
(FCount - Index) * SizeOf(Integer));
end;

procedure TIntList.Exchange(Index1, Index2: Integer);
var i:Integer;
begin
i:=Items[Index1];
Items[Index1]:=Items[Index2];
Items[Index2]:=i;
end;

function TIntList.Get(Index: Integer): Integer;
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.Create('TIntList.Get Index isnot valid!');
Result := FList^[Index];
end;

function TIntList.IndexOf(Item: Integer): Integer;
begin
Result := 0;
while (Result < FCount) and (FList^[Result] <> Item) do
Inc(Result);
if Result = FCount then
Result := -1;
end;

procedure TIntList.Put(Index: Integer
Item: Integer);
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.Create('TIntList.Put Index isnot valid!');
FList^[Index] := Item;
end;

procedure TIntList.LoadFromStream(Stream: TStream);
var Len:Integer;
begin
Clear;
Stream.Read(Len,SizeOf(Integer));
SetCount(Len);
Stream.Read(FList^[0],Len*SizeOf(Integer));
end;

procedure TIntList.SaveToStream(Stream: TStream);
var Len:Integer;
begin
Len:=Count;
Stream.Write(Len,SizeOf(Integer));
Stream.Write(FList^[0],Len*SizeOf(Integer));
end;

procedure TIntList.Grow;
var
Delta: Integer;
begin
if FCapacity > 64 then
Delta := FCapacity div 4
else
if FCapacity > 8 then
Delta := 16
else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;

procedure TIntList.Insert(Index, Item: Integer);
begin
if (Index < 0) or (Index > FCount) then
raise Exception.Create('TIntList.Insert Index isnot valid!');
if FCount = FCapacity then
Grow;
if Index < FCount then
System.Move(FList^[Index], FList^[Index + 1],(FCount - Index) * SizeOf(Integer));
FList^[Index] := Item;
Inc(FCount);
end;

function TIntList.IndexOfAfter(After, Item: Integer): Integer;
var i:Integer
//对包括索引After在内的Item进行检索
begin
Result:=-1;
for i :=After to FCount-1 do begin
if Items=Item then begin
Result:=i;
Exit;
end;
end;
end;

function TIntList.CountOfItem(Item: Integer): Integer;
var i:Integer;
begin
Result:=0;
for i :=0 to FCount-1 do begin
if Items=Item then begin
Inc(Result);
end;
end;
end;

function TIntList.Max: Integer;
var i:Integer;
begin
Result:=0;
if FCount=0 then Exit;
Result:=Items[0];
for i :=1 to FCount-1 do begin
if Items>Result then begin
Result:=Items;
end;
end;
end;

function TIntList.Remove(Item: Integer): Integer;
begin
Result := IndexOf(Item);
if Result >= 0 then
Delete(Result);
end;

procedure TIntList.Reset(Value: Integer);
var i:Integer;
begin //使用value值对所有Item填充
for i :=0 to Count-1 do begin
Items:=Value;
end;
end;

procedure TIntList.SetCount(NewCount: Integer);
var I: Integer;
begin
if (NewCount < 0) or (NewCount > MaxListSize) then
raise Exception.Create('TIntList.SetCount NewCount isnot valid!');
if NewCount > FCapacity then
SetCapacity(NewCount);
if NewCount > FCount then
FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Integer), 0)
else
for I := FCount - 1 downto NewCount do
Delete(I);
FCount := NewCount;
end;

procedure TIntList.SetCapacity(NewCapacity: Integer);
begin
if (NewCapacity < FCount) or (NewCapacity > MaxListLen) then
raise Exception.Create('TIntList.SetCapacity NewCapacity isnot valid!');
if NewCapacity <> FCapacity then begin
ReallocMem(FList, NewCapacity * SizeOf(Integer));
FCapacity := NewCapacity;
end;
end;

function TIntList.SumBefore(BeforeIndex: Integer): Integer;
var i:Integer;
begin
Result:=0;
for i :=0 to BeforeIndex-1 do begin
Result:=Result+items;
end;
end;

function TIntList.Sum(IndexArr: array of Integer): Integer;
var i,Index:Integer;
begin
Result:=0;
for i :=0 to Length(IndexArr)-1 do begin
Index:= IndexArr;
Result:=Result+Items[Index];
end;
end;

function TIntList.SumAll: Integer;
var i:Integer;
begin
Result:=0;
for i :=0 to Count-1 do begin
Result:=Result+Items;
end;
end;

procedure TIntList.Sort(araising: Boolean);
var i,j,aValue:Integer
//aIntList:TIntList;
function ItemCompare(Item1, Item2: Integer): TCompareResult;
begin
Result:=crSame;
if Item1=Item2 then Exit;
if Item1>Item2 then
Result:=crLarge
else
Result:=crSmall;
end;
begin
for i :=0 to Count-1 do begin
aValue:=Items;
for j :=i+1 to Count-1 do begin
if araising then begin
if ItemCompare(aValue,Items[j])=crLarge then
Exchange(i,j);
end else if ItemCompare(aValue,Items[j])=crSmall then begin
Exchange(i,j);
end;
end;
end;
end;

////////////////////////////////////////////////////////////////////////////////////

procedure TPointList.Assign(Source: TPersistent);
var i,Len:Integer;
aLst:TPointList;
begin
if not (Source is TPointList) then
raise Exception.Create('TPointList.Assign Source isnot valid!');
aLst:=(Source as TPointList);
Clear

Len:=aLst.Count;
SetCount(Len);
for i :=0 to Len-1 do begin
Items:=aLst.Items;
end;
end;

procedure TPointList.AssignTo(Dest: TPersistent);
begin
if not (Dest is TPointList) then
raise Exception.Create('TPointList.AssignTo Dest isnot valid!');
(Dest as TPointList).Assign(Self);
end;

destructor TPointList.Destroy;
begin
Clear;
end;

function TPointList.Add(Item: TPoint): Integer;
begin
Result := FCount;
if Result = FCapacity then
Grow;
FList^[Result] := Item;
Inc(FCount);
end;

procedure TPointList.Clear;
begin
SetCount(0);
SetCapacity(0);
end;

constructor TPointList.Create;
begin
inherited;
FCount:=0;
FCapacity:=0;
FList:=nil;
end;

procedure TPointList.Delete(Index: Integer);
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.Create('TPointList.Delete Index isnot valid!');
Dec(FCount);
if Index < FCount then
System.Move(FList^[Index + 1], FList^[Index],
(FCount - Index) * SizeOf(Integer));
end;

function TPointList.Get(Index: Integer): TPoint;
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.Create('TPointList.Get Index isnot valid!');
Result := FList^[Index];
end;

function TPointList.IndexOf(Item: TPoint): Integer;
begin
Result := 0;
while (Result < FCount) and (not IsSame(FList^[Result],Item)) do
Inc(Result);
if Result = FCount then
Result := -1;
end;

function TPointList.IsSame(Index1, Index2: Integer): Boolean;
begin
Result:=IsSame(FList^[Index1],FList^[Index2]);
end;

function TPointList.IsSame(Item1, Item2: TPoint): Boolean;
begin
Result:= (Item1.x=Item2.x)and(Item1.y=Item2.y);
end;

procedure TPointList.Put(Index: Integer
Item: TPoint);
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.Create('TPointList.Put Index isnot valid!');
FList^[Index] := Item;
end;

procedure TPointList.LoadFromStream(Stream: TStream);
var Len:Integer;
begin
Clear;
Stream.Read(Len,SizeOf(Integer));
SetCount(Len);
Stream.Read(FList^[0],Len*SizeOf(TPoint));
end;

procedure TPointList.SaveToStream(Stream: TStream);
var Len:Integer;
begin
Len:=Count;
Stream.Write(Len,SizeOf(Integer));
Stream.Write(FList^[0],Len*SizeOf(TPoint));
end;

procedure TPointList.Grow;
var Delta: Integer;
begin
if FCapacity > 64 then
Delta := FCapacity div 4
else
if FCapacity > 8 then
Delta := 16
else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;

procedure TPointList.Insert(Index:Integer
Item: TPoint);
begin
if (Index < 0) or (Index > FCount) then
raise Exception.Create('TPointList.Insert Index isnot valid!');
if FCount = FCapacity then
Grow;
if Index < FCount then
System.Move(FList^[Index], FList^[Index + 1],(FCount - Index) * SizeOf(TPoint));
FList^[Index] := Item;
Inc(FCount);
end;

function TPointList.Remove(Item: TPoint): Integer;
begin
Result := IndexOf(Item);
if Result >= 0 then
Delete(Result);
end;

procedure TPointList.SetCount(NewCount: Integer);
var I: Integer;
begin
if (NewCount < 0) or (NewCount > MaxListSize) then
raise Exception.Create('TPointList.SetCount NewCount isnot valid!');
if NewCount > FCapacity then
SetCapacity(NewCount);
if NewCount > FCount then
FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(TPoint), 0)
else
for I := FCount - 1 downto NewCount do
Delete(I);
FCount := NewCount;
end;

procedure TPointList.SetCapacity(NewCapacity: Integer);
begin
if (NewCapacity < FCount) or (NewCapacity > MaxListLen) then
raise Exception.Create('TPointList.SetCapacity NewCapacity isnot valid!');
if NewCapacity <> FCapacity then begin
ReallocMem(FList, NewCapacity * SizeOf(TPoint));
FCapacity := NewCapacity;
end;
end;
////////////////////////////////////////////////////////////////////////////////////



end.
 
简单一点,可以这样:
TIntegerList =Class
private

public
Items:array of integer;
Index:integer;
ItemsCount:integer;
Constructor Create;
procedure add(v:integer);
procedure Delete(Index:integer);
Destructor Destroy;
end;
 
我也做个一个类似的,好像比上面简单多了:
TFeatures = class //符号属性集类
private
FCount :SmallInt;
FFeatures :array of TFeature;
function GetCount :SmallInt;
function GetFeature(Index: Integer) :TFeature;
public
procedure Add(Feature: TFeature);
procedure Remove(Index: Integer);
procedure RemoveAll;
constructor Create
overload;
destructor Destroy
override;
property Items[Index: Integer] :TFeature read GetFeature;
published
property Count :SmallInt read GetCount;
end;
constructor TFeatures.Create;
begin
FCount:=0;
SetLength(FFeatures, FCount);
end;
destructor TFeatures.Destroy;
var
i:integer;
begin
for i:=0 to Length(FFeatures)-1 do FFeatures.Free;
inherited;
end;
procedure TFeatures.Add(Feature: TFeature);
begin
FCount:=Length(FFeatures);
SetLength(FFeatures, FCount+1);
FFeatures[FCount]:=Feature;
FCount:=FCount+1;
end;
procedure TFeatures.Remove(Index: Integer);
var
i : integer;
begin
if Index>FCount-1 then Application.MessageBox('此索引大于最大值!', '提示', 0)
else begin
for i:=Index to FCount-2 do FFeatures:=FFeatures[i+1];
FFeatures[FCount-1].Free;
FCount:=FCount-1;
SetLength(FFeatures, FCount);
end;
end;
procedure TFeatures.RemoveAll;
var
i:integer;
begin
for i:=0 to Length(FFeatures)-1 do FFeatures.Free;
FCount:=0;
SetLength(FFeatures, FCount);
end;
function TFeatures.GetFeature(Index: Integer): TFeature;
begin
Result:=nil;
if Index>FCount-1 then Application.MessageBox('此索引大于最大值!', '提示', 0)
else begin
Result:=FFeatures[Index];
end;
end;
function TFeatures.GetCount :SmallInt;
begin
FCount:=Length(FFeatures);
Result:=FCount;
end;
 
我还简单,根本不需要类,就用动态数组,
不过我为动态数组增加了 ADD,Delete 等类似List的function。
 
unit UnitClasses;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TIntegerList = class(TObject)
private
FList: TList;
function GetItems(Index: Integer): Int64;
procedure SetItems(Index: Integer
const Value: Int64);
function GetCount: Integer;
public
property Items[Index: Integer]: Int64 read GetItems write SetItems;
property Count: Integer read GetCount;

constructor Create;
destructor Destroy
override;

procedure Add(Value: Int64);
procedure Insert(Index: Integer
Value: Int64);
procedure Delete(Index: Integer);
procedure Clear;

end;

implementation

uses StdConvs;

{ TIntegerList }

procedure TIntegerList.Add(Value: Int64);
var
Tmp : PInt64;
begin
New(Tmp);
Tmp^ := Value;
try
FList.Add(Tmp);
except
Dispose(Tmp);
end;
end;

procedure TIntegerList.Clear;
var
I : Integer;
begin
for I := FList.Count - 1 downto 0 do
Dispose(FList);
FList.Clear;
end;

constructor TIntegerList.Create;
begin
FList := TList.Create;
end;

procedure TIntegerList.Delete(Index: Integer);
begin
Dispose(FList[Index]);
FList.Delete(Index);
end;

destructor TIntegerList.Destroy;
begin
FList.Free;
inherited Destroy;
end;

function TIntegerList.GetCount: Integer;
begin
Result := FList.Count;
end;

function TIntegerList.GetItems(Index: Integer): Int64;
begin
Result := Int64(FList[Index]^);
end;

procedure TIntegerList.Insert(Index: Integer
Value: Int64);
var
Tmp : PInt64;
begin
New(Tmp);
Tmp^ := Value;
try
FList.Insert(Index,Tmp);
except
Dispose(Tmp);
end;
end;

procedure TIntegerList.SetItems(Index: Integer
const Value: Int64);
begin
Int64(FList[Index]^) := Value;
end;

end.
 
楼上的几位都能实现,就效率而言,当属zuping的最好,因为它内部维护列表的是一个数组指针,写法与TList是一致的,但是Sort方法采用的是插入排序法,效率不好哦,建议采用快速排序法:)
yostgxf写的Remove过程效率不好.在列表项目多的情况下,循环次数太多影响效率,建议使用Move方法.
wr960204写的实际上还是使用了TList.如果这样的话,倒可以直接使用TList,
例如添加Add:
var P:PInteger;
begin
New(P);
P^=102;
List.Add(P);
end;
 
动态数组就行了,要再封装几个读写方法,Create, 等等就ok
 
后退
顶部