我做过类似的类,直接使用就是了,也是仿照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.