我有一个从1到10000000的数array of [0..10000000-1] of Byte;最开始进入时,全部空闲,都设置为1, 被使用后,设置为0,判断连续的n个数,遍历比较n DIV 4个整数如果是$1111然后比较之后的(n and 3)个Byte,如果都是1,即得到连续的n个数,数字就是序号
贴一下我的代码,我感觉我这个效率一般,请各位路过的大哥帮忙看看能不能优化,或给出其他算法!主要是查询出来后原要放回原来的队列program Project1;{$APPTYPE CONSOLE}uses SysUtils, Windows;type PSBTNode = ^TSBTNode; TSBTNode = record count: Cardinal; data: Cardinal; size: Cardinal; lch,rch: PSBTNode; end; TSBT = class private // 节点数组 m_Buckets: array of PSBTNode; // 节点数 NodeCount: Cardinal; // 根节点,空节点 root,null: PSBTNode; // 初始化 procedure NodeInit(ACount: Cardinal); // 清除 procedure NodeClear; // 左旋转 procedure lrotate(var x: PSBTNode); inline; // 右旋转 procedure rrotate(var x: PSBTNode); inline; // 保持性质 procedure maintain(var t: PSBTNode; const flag: Boolean); inline; // 增加 procedure TreeAdd(var t: PSBTNode; v: PSBTNode); inline; // 移除 function TreeRemove(var t: PSBTNode; var n: PSBTNode; v: Cardinal): Cardinal; inline; // 返回第 x 大的元素 function TreeSelect(var t: PSBTNode; k: Cardinal): Cardinal; inline; // 查找 function TreeFind(var t: PSBTNode; v: Cardinal): Boolean; inline; // 排名 function TreeRank(var t: PSBTNode; v: Cardinal): Cardinal; inline; // 向前,大 function TreeSucc(var t: PSBTNode; v: Cardinal): Cardinal; inline; // 向后,小 function TreePred(var t: PSBTNode; v: Cardinal): Cardinal; inline; public constructor Create(ACount: Cardinal); destructor Destroy; override; procedure add(v: PSBTNode); function remove(v: Cardinal): PSBTNode; function select(k: Cardinal): Cardinal; inline; function find(v: Cardinal): Boolean; inline; function rank(v: Cardinal): Cardinal; inline; function succ(v: Cardinal): Cardinal; inline; function pred(v: Cardinal): Cardinal; inline; function dwGet(N: Integer): Cardinal; function dwRes(P: Cardinal): Boolean; end;{ TSBT } constructor TSBT.Create(ACount: Cardinal); begin NodeCount := 0; new(null); null^.data := 0; null^.size := 0; null^.lch := null; null^.rch := null; root := null; NodeInit(ACount); end;destructor TSBT.Destroy; begin NodeClear; NodeCount := 0; Dispose(null); inherited Destroy; end;procedure TSBT.NodeInit(ACount: Cardinal); var I: Integer; begin SetLength(m_Buckets, ACount); for I := 0 to ACount-1 do begin New(m_Buckets[I]); m_Buckets[I]^.data := I; add(m_Buckets[I]); end; end;procedure TSBT.NodeClear; var I: Integer; begin for I := 0 to Length(m_Buckets)-1 do begin Dispose(m_Buckets[I]); end; end;procedure TSBT.lrotate(var x: PSBTNode); var y: PSBTNode; begin y := x^.rch; x^.rch := y^.lch; y^.lch := x; y^.size := x^.size; x^.size := x^.lch^.size+x^.rch^.size+1; x := y; end;procedure TSBT.rrotate(var x: PSBTNode); var y: PSBTNode; begin y := x^.lch; x^.lch := y^.rch; y^.rch := x; y^.size := x^.size; x^.size := x^.lch^.size+x^.rch^.size+1; x := y; end;procedure TSBT.maintain(var t: PSBTNode; const flag: Boolean); begin if t=null then exit; if not flag then if t^.lch^.lch^.size>t^.rch^.size then rrotate(t) else if t^.lch^.rch^.size>t^.rch^.size then begin lrotate(t^.lch); rrotate(t); end else exit else if t^.rch^.rch^.size>t^.lch^.size then lrotate(t) else if t^.rch^.lch^.size>t^.lch^.size then begin rrotate(t^.rch); lrotate(t); end else exit; maintain(t^.lch, false); maintain(t^.rch, true); maintain(t, false); maintain(t, true); end;procedure TSBT.TreeAdd(var t: PSBTNode; v: PSBTNode); begin if t=null then begin t := v; t^.count := 0; t^.size := 1; t^.lch := null; t^.rch := null; Inc(NodeCount); end else begin inc(t^.size); if v^.data<t^.data then TreeAdd(t^.lch, v) else TreeAdd(t^.rch, v); maintain(t, v^.data>=t^.data); end; end;function TSBT.TreeRemove(var t: PSBTNode; var n: PSBTNode; v: Cardinal): Cardinal; var tmp: PSBTNode; begin Result := Cardinal(-1); if t=null then Exit; dec(t^.size); if(v=t^.data) or ((v<t^.data) and (t^.lch=null)) or ((v>t^.data) and (t^.rch=null)) then begin Result := t^.data; if(t^.lch=null) or (t^.rch=null) then begin if t^.lch=null then begin tmp := t; t := tmp^.rch; if tmp<>null then begin n := tmp; Dec(NodeCount); Exit; end; end; if t^.rch=null then begin tmp := t; t := tmp^.lch; if tmp<>null then begin n := tmp; Dec(NodeCount); Exit; end; end; end else t^.data := TreeRemove(t^.lch, n, t^.data+1); end else if v<t^.data then Result := TreeRemove(t^.lch, n, v) else Result := TreeRemove(t^.rch, n, v); end;function TSBT.TreeSelect(var t: PSBTNode; k: Cardinal): Cardinal; begin if (k=t^.lch^.size+1) then begin Result := t^.data; exit; end; if k<=t^.lch^.size then Result := TreeSelect(t^.lch, k) else Result := TreeSelect(t^.rch, k-1-t^.lch^.size); end;function TSBT.TreeFind(var t: PSBTNode; v: Cardinal): Boolean; begin if t=null then begin Result := false; exit; end; if v<t^.data then Result := TreeFind(t^.lch,v) else Result := (v=t^.data) or TreeFind(t^.rch,v); end;function TSBT.TreeRank(var t: PSBTNode; v: Cardinal): Cardinal; begin if t=null then begin Result := 1; exit; end; if v<t^.data then Result := TreeRank(t^.lch,v) else Result := t^.lch^.size+1+TreeRank(t^.rch,v); end;function TSBT.TreeSucc(var t: PSBTNode; v: Cardinal): Cardinal; var tmp:Cardinal; begin if t=null then begin Result := v; exit; end; if v>=t^.data then Result := TreeSucc(t^.rch,v) else begin tmp:=TreeSucc(t^.lch,v); if tmp=v then tmp := t^.data; Result := tmp; end; end;function TSBT.TreePred(var t: PSBTNode; v: Cardinal): Cardinal; var tmp: Cardinal; begin if t=null then begin Result := v; exit; end; if v<=t^.data then Result := TreePred(t^.lch, v) else begin tmp := TreePred(t^.rch,v); if tmp=v then tmp := t^.data; Result := tmp; end; end;procedure TSBT.add(v: PSBTNode); begin TreeAdd(root, v); end;function TSBT.remove(v: Cardinal): PSBTNode; var v2: Cardinal; P: PSBTNode; begin Result := nil; TreeRemove(root, Result, v); v2 := Result^.data; Result^.data := v; //位置交换 P := m_Buckets[v2]; m_Buckets[v2] := m_Buckets[v]; m_Buckets[v] := P; end;function TSBT.select(k: Cardinal): Cardinal; begin Result := TreeSelect(root, k); end;function TSBT.find(v: Cardinal): Boolean; begin Result := TreeFind(root, v); end;function TSBT.rank(v: Cardinal): Cardinal; begin Result := TreeRank(root, v); end;function TSBT.succ(v: Cardinal): Cardinal; begin Result := TreeSucc(root, v); end;function TSBT.pred(v: Cardinal): Cardinal; begin Result := TreePred(root, v); end;function TSBT.dwGet(N: Integer): Cardinal; var M, D1, D2, NStart, NEnd: Integer; P: PSBTNode; begin M := 1; D2 := -1; D1 := select(1); if N<=1 then begin NStart := D1; //移出使用中的对像 P := remove(NStart); P^.count := 1; Result := P^.data; Exit; end; while True do begin //右旋转 D2 := succ(D1); if D2=D1 then Break; if D2=D1+1 then begin Inc(M); end else begin M := 1; end; if M>=N then Break; D1 := D2; end; NStart := D2 - N + 1; NEnd := NStart + N; P := remove(NStart); P^.count := N; Result := P^.data; Inc(NStart); while NStart<NEnd do begin //移出使用中的对像 remove(NStart); Inc(NStart); end; end;function TSBT.dwRes(P: Cardinal): Boolean; var M, N, NEnd: Cardinal; begin M := P; // 页数 N := m_Buckets[M]^.count; NEnd := M + N; // 放回 while M<NEnd do begin add(m_Buckets[M]); Inc(M); end; Result := True; end;var _SBT: TSBT; I: Integer; aaa: array of Cardinal; n1,n2: Int64;begin try { TODO -oUser -cConsole Main : Insert code here } Writeln('初始化.'); QueryPerformanceCounter(n1); _SBT := TSBT.Create(10000000); QueryPerformanceCounter(n2); Writeln('初始耗时:', (n2-n1) div 1000, 'ms'); Readln; try SetLength(aaa, 1000000); //申请 Writeln('查找.'); Randomize; QueryPerformanceCounter(n1); for I := 0 to 999999 do begin aaa[I] := _SBT.dwGet(5); end; QueryPerformanceCounter(n2); Writeln('查找耗时:', (n2-n1) div 1000, 'ms'); Readln; //放回 Writeln('放回.'); QueryPerformanceCounter(n1); for I := 0 to 999999 do begin _SBT.dwRes(aaa[I]); end; QueryPerformanceCounter(n2); Writeln('放回耗时:', (n2-n1) div 1000, 'ms'); Readln; finally FreeAndNil(_SBT); end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
最后再请cngst大哥帮忙看看我完整的应用应该是这样,cngst大哥的算法非常快,但我还是没办法使用到我这个应用中来,现在我贴出我完整理应用的代码,请大哥费神再帮忙看一下!分页式虚拟内存管理 unit uVirtualMemPool;interfaceuses SysUtils, Windows;type TVirtualMemPool = class; PSBTNode = ^TSBTNode; TSBTNode = record IsUse: Boolean; //是否使用中 count: Cardinal; //使用页数 value: Pointer; //内存地址 data: Cardinal; //节点序号 size: Cardinal; //子节点数 lch,rch: PSBTNode; //左右节点 end; // 平衡二叉查找树SBT TSizeBalancedTree = class private VMPool: TVirtualMemPool; // 节点数 NodeCount: Cardinal; // 根节点,空节点 root,null: PSBTNode; // 左旋转 procedure lrotate(var x: PSBTNode); inline; // 右旋转 procedure rrotate(var x: PSBTNode); inline; // 保持性质 procedure maintain(var t: PSBTNode; const flag: Boolean); inline; // 增加 procedure TreeAdd(var t: PSBTNode; v: PSBTNode); inline; // 移除 function TreeRemove(var t: PSBTNode; var n: PSBTNode; v: Cardinal): Cardinal; inline; // 返回第 x 大的元素 function TreeSelect(var t: PSBTNode; k: Cardinal): Cardinal; inline; // 查找 function TreeFind(var t: PSBTNode; v: Cardinal): Boolean; inline; // 排名 function TreeRank(var t: PSBTNode; v: Cardinal): Cardinal; inline; // 向前,大 function TreeSucc(var t: PSBTNode; v: Cardinal): Cardinal; inline; // 向后,小 function TreePred(var t: PSBTNode; v: Cardinal): Cardinal; inline; public constructor Create(AVMpool: TVirtualMemPool); destructor Destroy; override; procedure add(v: PSBTNode); function remove(v: Cardinal): PSBTNode; function select(k: Cardinal): Cardinal; inline; function find(v: Cardinal): Boolean; inline; function rank(v: Cardinal): Cardinal; inline; function succ(v: Cardinal): Cardinal; inline; function pred(v: Cardinal): Cardinal; inline; end; // 内存管理 TVirtualMemPool = class public m_VMLock: TRTLCriticalSection; m_NMLock: TRTLCriticalSection; m_PageSize: Cardinal; m_Count: Cardinal; m_lpBase: Pointer; m_Buckets: array of PSBTNode; m_SBTStorage: TSizeBalancedTree; private function GetCount: Cardinal; function GetUseCount: Cardinal; function GetFreeCount: Cardinal; procedure InitMemPool(ACount: Integer); procedure Clear; public property Count: Cardinal read GetCount; property UseCount: Cardinal read GetUseCount; property FreeCount: Cardinal read GetFreeCount; public constructor Create(ACount: Integer); destructor Destroy; override; public function VMAlloc(dwSize: Cardinal; IsLock: Boolean = True): Pointer; function VMReAlloc(var P; dwSize: Cardinal): Pointer; function VMFree(var P; IsLock: Boolean = True): Boolean; end;implementation
{ TSizeBalancedTree } constructor TSizeBalancedTree.Create(AVMpool: TVirtualMemPool); begin VMPool := AVMpool; NodeCount := 0; new(null); null^.data := 0; null^.size := 0; null^.lch := null; null^.rch := null; root := null; end;destructor TSizeBalancedTree.Destroy; begin NodeCount := 0; Dispose(null); inherited Destroy; end;procedure TSizeBalancedTree.lrotate(var x: PSBTNode); var y: PSBTNode; begin y := x^.rch; x^.rch := y^.lch; y^.lch := x; y^.size := x^.size; x^.size := x^.lch^.size+x^.rch^.size+1; x := y; end;procedure TSizeBalancedTree.rrotate(var x: PSBTNode); var y: PSBTNode; begin y := x^.lch; x^.lch := y^.rch; y^.rch := x; y^.size := x^.size; x^.size := x^.lch^.size+x^.rch^.size+1; x := y; end;procedure TSizeBalancedTree.maintain(var t: PSBTNode; const flag: Boolean); begin if t=null then exit; if not flag then if t^.lch^.lch^.size>t^.rch^.size then rrotate(t) else if t^.lch^.rch^.size>t^.rch^.size then begin lrotate(t^.lch); rrotate(t); end else exit else if t^.rch^.rch^.size>t^.lch^.size then lrotate(t) else if t^.rch^.lch^.size>t^.lch^.size then begin rrotate(t^.rch); lrotate(t); end else exit; maintain(t^.lch, false); maintain(t^.rch, true); maintain(t, false); maintain(t, true); end;procedure TSizeBalancedTree.TreeAdd(var t: PSBTNode; v: PSBTNode); begin if t=null then begin t := v; //进入的内存设置为未使用 t^.IsUse := False; t^.count := 0; t^.size := 1; t^.lch := null; t^.rch := null; Inc(NodeCount); end else begin inc(t^.size); if v^.data<t^.data then TreeAdd(t^.lch, v) else TreeAdd(t^.rch, v); maintain(t, v^.data>=t^.data); end; end;function TSizeBalancedTree.TreeRemove(var t: PSBTNode; var n: PSBTNode; v: Cardinal): Cardinal; var tmp: PSBTNode; begin Result := Cardinal(-1); if t=null then Exit; dec(t^.size); if(v=t^.data) or ((v<t^.data) and (t^.lch=null)) or ((v>t^.data) and (t^.rch=null)) then begin Result := t^.data; if(t^.lch=null) or (t^.rch=null) then begin if t^.lch=null then begin tmp := t; t := tmp^.rch; if tmp<>null then begin n := tmp; Dec(NodeCount); Exit; end; end; if t^.rch=null then begin tmp := t; t := tmp^.lch; if tmp<>null then begin n := tmp; Dec(NodeCount); Exit; end; end; end else t^.data := TreeRemove(t^.lch, n, t^.data+1); end else if v<t^.data then Result := TreeRemove(t^.lch, n, v) else Result := TreeRemove(t^.rch, n, v); end;function TSizeBalancedTree.TreeSelect(var t: PSBTNode; k: Cardinal): Cardinal; begin if (k=t^.lch^.size+1) then begin Result := t^.data; exit; end; if k<=t^.lch^.size then Result := TreeSelect(t^.lch, k) else Result := TreeSelect(t^.rch, k-1-t^.lch^.size); end;function TSizeBalancedTree.TreeFind(var t: PSBTNode; v: Cardinal): Boolean; begin if t=null then begin Result := false; exit; end; if v<t^.data then Result := TreeFind(t^.lch,v) else Result := (v=t^.data) or TreeFind(t^.rch,v); end;function TSizeBalancedTree.TreeRank(var t: PSBTNode; v: Cardinal): Cardinal; begin if t=null then begin Result := 1; exit; end; if v<t^.data then Result := TreeRank(t^.lch,v) else Result := t^.lch^.size+1+TreeRank(t^.rch,v); end;function TSizeBalancedTree.TreeSucc(var t: PSBTNode; v: Cardinal): Cardinal; var tmp:Cardinal; begin if t=null then begin Result := v; exit; end; if v>=t^.data then Result := TreeSucc(t^.rch,v) else begin tmp:=TreeSucc(t^.lch,v); if tmp=v then tmp := t^.data; Result := tmp; end; end;function TSizeBalancedTree.TreePred(var t: PSBTNode; v: Cardinal): Cardinal; var tmp: Cardinal; begin if t=null then begin Result := v; exit; end; if v<=t^.data then Result := TreePred(t^.lch, v) else begin tmp := TreePred(t^.rch,v); if tmp=v then tmp := t^.data; Result := tmp; end; end;procedure TSizeBalancedTree.add(v: PSBTNode); begin TreeAdd(root, v); end;function TSizeBalancedTree.remove(v: Cardinal): PSBTNode; var v2: Cardinal; C: Pointer; P: PSBTNode; begin Result := nil; TreeRemove(root, Result, v); v2 := Result^.data; Result^.data := v; //移出的内存设置为使用 Result^.IsUse := True; //value交换 C := VMPool.m_Buckets[v2]^.value; VMPool.m_Buckets[v2]^.value := VMPool.m_Buckets[v]^.value; VMPool.m_Buckets[v]^.value := C; //位置交换 P := VMPool.m_Buckets[v2]; VMPool.m_Buckets[v2] := VMPool.m_Buckets[v]; VMPool.m_Buckets[v] := P; end;function TSizeBalancedTree.select(k: Cardinal): Cardinal; begin Result := TreeSelect(root, k); end;function TSizeBalancedTree.find(v: Cardinal): Boolean; begin Result := TreeFind(root, v); end;function TSizeBalancedTree.rank(v: Cardinal): Cardinal; begin Result := TreeRank(root, v); end;function TSizeBalancedTree.succ(v: Cardinal): Cardinal; begin Result := TreeSucc(root, v); end;function TSizeBalancedTree.pred(v: Cardinal): Cardinal; begin Result := TreePred(root, v); end;
{ TVirtualMemPool } constructor TVirtualMemPool.Create(ACount: Integer); var SysInfo: TSystemInfo; begin inherited Create;; InitializeCriticalSection(m_VMLock); InitializeCriticalSection(m_NMLock); GetSystemInfo(SysInfo); m_PageSize := SysInfo.dwPageSize; m_SBTStorage := TSizeBalancedTree.Create(Self); m_Count := ACount; InitMemPool(m_Count); end;destructor TVirtualMemPool.Destroy; begin FreeAndNil(m_SBTStorage); Clear; VirtualFree(m_lpBase, 0, MEM_RELEASE); DeleteCriticalSection(m_NMLock); DeleteCriticalSection(m_VMLock); inherited Destroy; end;function TVirtualMemPool.GetCount: Cardinal; begin Result := m_Count; end;function TVirtualMemPool.GetUseCount: Cardinal; begin EnterCriticalSection(m_NMLock); try Result := m_Count - m_SBTStorage.NodeCount; finally LeaveCriticalSection(m_NMLock); end; end;function TVirtualMemPool.GetFreeCount: Cardinal; begin EnterCriticalSection(m_NMLock); try Result := m_SBTStorage.NodeCount; finally LeaveCriticalSection(m_NMLock); end; end;procedure TVirtualMemPool.InitMemPool(ACount: Integer); var I: Integer; begin EnterCriticalSection(m_VMLock); try // 申请大块内存 m_lpBase := VirtualAlloc(nil, ACount*m_PageSize, MEM_RESERVE, PAGE_NOACCESS); SetLength(m_Buckets, ACount); //debug('m_lpBase: %d, NumberOfNode: %d', [Cardinal(m_lpBase), NumberOfNode]); for I := 0 to ACount-1 do begin { 为第I页地址提交内存。 } New(m_Buckets[I]); m_Buckets[I]^.data := I; m_Buckets[I]^.value := VirtualAlloc(Pointer(Cardinal(m_lpBase)+(I*m_PageSize)), m_PageSize, MEM_COMMIT, PAGE_READWRITE); //debug('I: %d=%d', [I, Cardinal(m_Buckets[I]^.value)]); //ZeroMemory(m_Buckets[I]^.value, m_PageSize); m_SBTStorage.add(m_Buckets[I]); end; finally LeaveCriticalSection(m_VMLock); end; end;procedure TVirtualMemPool.Clear; var I: Integer; begin EnterCriticalSection(m_VMLock); try for I := 0 to Length(m_Buckets)-1 do begin Dispose(m_Buckets[I]); end; finally LeaveCriticalSection(m_VMLock); end; end;function TVirtualMemPool.VMAlloc(dwSize: Cardinal; IsLock: Boolean = True): Pointer; var N, M, D1, D2, NStart, NEnd: Integer; P: PSBTNode; begin if FreeCount<=0 then begin Result := nil; raise Exception.Create('No free pages in main memory.'); Exit; end; if IsLock then EnterCriticalSection(m_VMLock); try N := dwSize div m_PageSize; if (dwSize mod m_PageSize)<>0 then Inc(N); M := 1; D2 := -1; D1 := m_SBTStorage.select(1); if N<=1 then begin NStart := D1; //移出使用中的对像 P := m_SBTStorage.remove(NStart); P^.count := 1; Result := P^.value; Exit; end; while True do begin //右旋转 D2 := m_SBTStorage.succ(D1); if D2=D1 then Break; if D2=D1+1 then begin Inc(M); end else begin M := 1; end; if M>=N then Break; D1 := D2; end; NStart := D2 - N + 1; NEnd := NStart + N; P := m_SBTStorage.remove(NStart); P^.count := N; Result := P^.value; Inc(NStart); while NStart<NEnd do begin m_SBTStorage.remove(NStart); Inc(NStart); end; finally if IsLock then LeaveCriticalSection(m_VMLock); end; end;function TVirtualMemPool.VMReAlloc(var P; dwSize: Cardinal): Pointer; var OldN, M, NewN, NEnd: Cardinal; NewP: Pointer; begin Result := nil; if Pointer(P)=nil then begin Result := VMAlloc(dwSize); Exit; end; EnterCriticalSection(m_VMLock); try M := (Cardinal(Pointer(P))-Cardinal(m_lpBase)) div m_PageSize; // 原页数 OldN := m_Buckets[M]^.count; // 新页数 NewN := dwSize div m_PageSize; if (dwSize mod m_PageSize)<>0 then Inc(NewN); // 新页数=原页数 if NewN=OldN then begin Result := Pointer(P); end // 新页数<原页数,多余的页放回页表 else if NewN<OldN then begin NEnd := M + OldN; m_Buckets[M]^.count := OldN-NewN; M := M + NewN; while M<NEnd do begin m_SBTStorage.add(m_Buckets[M]); Inc(M); end; Result := Pointer(P); end // 新页数>原页数,重新申请并Copy原数据到新数据 else if NewN>OldN then begin NewP := VMAlloc(dwSize, False); //原数据Copy到新数据中 if NewP<>nil then CopyMemory(NewP, Pointer(P), OldN*m_PageSize); //放回原页数 VMFree(P, False); //返回 Pointer(P) := NewP; Result := NewP; end; finally LeaveCriticalSection(m_VMLock); end; end;function TVirtualMemPool.VMFree(var P; IsLock: Boolean = True): Boolean; var M, N, NEnd: Cardinal; begin if IsLock then EnterCriticalSection(m_VMLock); try M := (Cardinal(Pointer(P))-Cardinal(m_lpBase)) div m_PageSize; Pointer(P) := nil; // 页数 N := m_Buckets[M]^.count; NEnd := M + N; // 放回 while M<NEnd do begin m_SBTStorage.add(m_Buckets[M]); Inc(M); end; finally if IsLock then LeaveCriticalSection(m_VMLock); end; Result := True; end;end.//使用方法 var VMP: TVirtualMemPool; P: PAnsiChar; S: AnsiString; begin VMP := TVirtualMemPool.Create(200000); try //分配 P := VMP.VMAlloc(4096*3); Writeln(Cardinal(P)); S := 'ABCDEFG'; CopyMemory(P, @S[1], Length(S)); FillChar(P^, 4096*3, 88); //重新分配 P := VMP.VMReAlloc(P, 4096*6); Writeln(Cardinal(P)); //回收 VMP.VMFree(P); if P=nil then Writeln('OK'); Readln; finally FreeAndNil(VMP); end; end;//我这里是按页大小分配的,页大小4096,如果分配3页就是4096*3,相当于,查找3个连续的数!希望cngst大哥帮我看看,或有其他高手提供好的算法! 非常感谢cngst大哥和上面的各位高手,这个贴子完成后是不是可以推荐到首页呢?
你给它拼成一个字符串, 然后做字符串查找就行了, KMP算法和DELPHI自带的POSEX都可以
比如有5个数(当然实际有10000000个数),1、2、3、6、9,清除连续3个的数后,结果剩余6、9两个数,并将其存在目标数据的前两位。不知道是不是楼主想要的结果。代码如下:
const
AllCount=10000000; //总的数据量
One_tenth=1000000; //十分之一
//声明三个全局变量:
var
tmpData:pdword;
DataCount:dword; //每次清除后剩余的数据量
Data:array of dword; //存贮数据的数组
//下面是三个函数:procedure initData; //分配内存,初始化数组
asm
pushad
mov eax,AllCount
mov DataCount,eax
push eax
shl eax,2
call sysgetmem
mov Data,eax
xor edx,edx
pop ecx
@p1:
inc edx
mov [eax],edx
add eax,4
loop @p1
mov eax,allCount
shl eax,2
call sysgetmem
mov tmpData,eax
popad
end;procedure ClearOne_tenth; //清除十分之一的数据
asm
pushad
mov eax,Data
mov edx,tmpData
mov ecx,DataCount
shl ecx,2
call Move
mov esi,tmpData
mov ecx,One_tenth
mov eax,DataCount
@p1:
push eax
push ecx
call random
pop ecx
shl eax,2
cmp dword ptr[esi+eax],0
jnz @p2
pop eax
jmp @p1
@p2:
mov dword ptr [esi+eax],0
pop eax
loop @p1
mov ecx,eax
sub eax,One_tenth
mov DataCount,eax
mov edi,Data
@p3:
cmp dword ptr[esi],0
jz @p4
mov edx,[esi]
mov [edi],edx
add edi,4
@p4:
add esi,4
loop @p3
popad
end;procedure ClearContinuous(cnt:dword); //随机清除所有cnt个连续的数据
asm
pushad
push eax
mov eax,Data
mov edx,tmpData
mov ecx,DataCount
shl ecx,2
call Move
pop eax
mov ecx,DataCount
dec ecx
mov esi,tmpData
xor edx,edx
inc edx
@p1:
mov ebx,[esi+4]
sub ebx,[esi]
cmp ebx,1
je @p2
xor edx,edx
@p2:
inc edx
cmp edx,eax
jne @p3
mov dword ptr[esi+4],0
pushad
sub esi,eax
sub esi,eax
sub esi,eax
sub esi,eax
add esi,8
mov ecx,eax
dec ecx
@p4:
mov dword ptr[esi],0
add esi,4
loop @p4
popad
@p3:
add esi,4
loop @p1 mov esi,tmpData
mov edi,Data
mov ecx,DataCount
xor eax,eax @p5:
cmp dword ptr[esi],0
jz @p6
mov edx,[esi]
mov [edi],edx
add edi,4
inc eax
@p6:
add esi,4
loop @p5
mov DataCount,eax
popad
end;
使用方法:var old1,old2,old3:dword;
i:integer;
tmps:string;
begin
randomize;
old1:=gettickcount;
initData; //初始化数据
old1:=gettickcount-old1;
old2:=gettickcount;
ClearOne_tenth; //随机清除十分之一的数据
old2:=gettickcount-old2;
old3:=gettickcount;
ClearContinuous(6); //快速从剩余的数中查找出连续6个的数并清除
old3:=gettickcount-old3; showmessage(format('初始化数组用时:%d 毫秒,清除十分之一用时:%d 毫秒'+#13+#10
+'清除连续6个的数用时:%d 毫秒'+#13+#10+'最后剩余数字量:%d',[old1,old2,old3,DataCount]));在我的电脑中,清除用时不到0.1秒。如果不需要重新排列数字,保持数字原来在数据中的位置,速度还可以快很多。
稍作修改,加了一个数组:Clsed,用于存贮连续数的头一个数。并加了一个释放内存的函数:const
AllCount=10000000; //总的数据量
One_tenth=1000000; //十分之一
//声明全局变量:
var
tmpData:pdword;
DataCount:dword; //每次清除后剩余的数据量
Data:array of dword; //存贮数据的数组
Clsed:array of dword; //存贮被清除的连续数的第一个数
ClsCnt:dword; //被清除的连续数的组数//下面是四个函数(新增一个释放内存的函数):procedure initData; //分配内存,初始化数组
asm
pushad
mov eax,AllCount
mov DataCount,eax
push eax
shl eax,2
call sysgetmem
mov Data,eax
xor edx,edx
pop ecx
@p1:
inc edx
mov [eax],edx
add eax,4
loop @p1
mov eax,allCount
shl eax,2
call sysgetmem
mov tmpData,eax
mov eax,allCount
shl eax,1
call sysgetmem
mov Clsed,eax
popad
end;procedure ClearOne_tenth; //随机清除十分之一的数据
asm
pushad
mov eax,Data
mov edx,tmpData
mov ecx,DataCount
shl ecx,2
call Move
mov esi,tmpData
mov ecx,One_tenth
mov eax,DataCount
@p1:
push eax
push ecx
call random
pop ecx
shl eax,2
cmp dword ptr[esi+eax],0
jnz @p2
pop eax
jmp @p1
@p2:
mov dword ptr [esi+eax],0
pop eax
loop @p1
mov ecx,eax
sub eax,One_tenth
mov DataCount,eax
mov edi,Data
@p3:
cmp dword ptr[esi],0
jz @p4
mov edx,[esi]
mov [edi],edx
add edi,4
@p4:
add esi,4
loop @p3
popad
end;procedure ClearContinuous(cnt:dword); //清除所有cnt个连续的数据
asm
pushad
push eax
mov eax,Data
mov edx,tmpData
mov ecx,DataCount
shl ecx,2
call Move
pop eax
mov ecx,DataCount
dec ecx
mov esi,tmpData
mov edi,Clsed
xor edx,edx
inc edx
@p1:
mov ebx,[esi+4]
sub ebx,[esi]
cmp ebx,1
je @p2
xor edx,edx
@p2:
inc edx
cmp edx,eax
jne @p3
mov dword ptr[esi+4],0
pushad
sub esi,eax
sub esi,eax
sub esi,eax
sub esi,eax
add esi,8
mov edx,[esi]
mov [edi],edx
mov ecx,eax
dec ecx
@p4:
mov dword ptr[esi],0
add esi,4
loop @p4
popad
add edi,4
@p3:
add esi,4
loop @p1 mov eax,clsed
sub edi,eax
shr edi,2
mov clscnt,edi mov esi,tmpData
mov edi,Data
mov ecx,DataCount
xor eax,eax @p5:
cmp dword ptr[esi],0
jz @p6
mov edx,[esi]
mov [edi],edx
add edi,4
inc eax
@p6:
add esi,4
loop @p5
mov DataCount,eax
popad
end;procedure FreeData; //释放内存
asm
mov eax,tmpData
call sysfreemem
mov eax,Data
call sysfreemem
mov eax,clsed
call sysfreemem
xor eax,eax
mov DataCount,eax
mov ClsCnt,eax
mov Data,eax
mov clsed,eax
end;
使用方法:var old1,old2,old3:dword;
begin
randomize;
old1:=gettickcount;
initData; //初始化数据
old1:=gettickcount-old1;
old2:=gettickcount;
ClearOne_tenth; //随机清除十分之一的数据
old2:=gettickcount-old2;
old3:=gettickcount;
ClearContinuous(6); //快速从剩余的数中查找出连续6个的数并清除
old3:=gettickcount-old3; showmessage(format('初始化数组用时:%d 毫秒,清除十分之一用时:%d 毫秒'+#13+#10
+'清除连续6个的数用时:%d 毫秒'+#13+#10+'最后剩余数字量:%d'
+#13+#10+'被清除的组数:%d',[old1,old2,old3,DataCount,ClsCnt]));// freedata; //释放内存(如果要继续清除,就暂时不要释放内存)
只有那个从页表内查找n个连续的页并将这几个页从页表中移除(或设置为已使用),这n个连续的页使用完成后再按页的序号插入原页表队列中去,供下次使用另外cngst大哥能帮忙改成delphi的吗?你那个asm我只能看懂mov xor call之类的东西,过程的n-m参数是哪个寄存器我都不明白
是遍历比较n DIV 4个整数如果是$01010101,
(n shl 2)更好些
貌似用一个双向链表倒是可以快不少,但我相信查询移出和插入肯定还有更快的算法!不知道哪位高手能给点思路另外我看asm和看天书没两样
我这样实现不知道速度怎么样
假设n=5
那么你就用折半的办法 首先10000个数的1-5个数先取出, 假设1-5的数是 6 5 7 8 9 首先判断 7的前两位是否是5(7-2) 不是的话判断后面的数是不是9(7+2) 如果是的话继续判断9的后面是不是11(9+2)
如果你n多的话建议用这个办法
1到1亿里面, 随机抽取10分一的数走, 每次抽取, 总是抽了一次以后就不能抽走吧..
那么首先, 在链表里面只有1个结点.
List:
Node1->1 ~ 1亿.
从里面抽掉了一个数, 例如9, 那么链表就变成:
List:
Node1->1 ~ 8
Node2->10 ~ 1亿.
如此类推, 抽走10份之一的数走了, 那么链表最坏的情况是被拆开1亿/10那么多份, 但也有可能只分成为两份, 最终要看抽取的数据是在每个结点范围的内的值还是结点范围的边界值而定, 边界值是不需要分分分裂的.有了这样的一个链表...我想剩下怎样去掉任意连续长度的块..很容易了吧...
假如分裂的结点是带有内存池方式, 会分裂得更快. 1亿以内的运算, 现在家用电脑也不成问题了, 保证清除时快于0.1S, 每个结点从头到尾都有最大值和最小值, 并且是肯定连续的, 取余运算, 直接就得到当前的块能够乘余哪个段了. 小于nCnt则直接跳过.
cngst大哥的我用了一下begin
try
{ TODO -oUser -cConsole Main : Insert code here }
randomize;
old1:=gettickcount;
initData; //初始化数据
old1:=gettickcount-old1;
old2:=gettickcount;
ClearOne_tenth; //随机清除十分之一的数据
old2:=gettickcount-old2;
//randomize;
old3:=gettickcount;
for I := 0 to 99999 do
begin
ClearContinuous(6); //快速从剩余的数中查找出连续6个的数并清除
end;
old3:=gettickcount-old3; WriteLn(format('初始化数组用时:%d 毫秒,清除十分之一用时:%d 毫秒'+#13+#10
+'清除连续6个的数用时:%d 毫秒'+#13+#10+'最后剩余数字量:%d'
+#13+#10+'被清除的组数:%d',[old1,old2,old3,DataCount,ClsCnt]));// freedata; //释放内存(如果要继续清除,就暂时不要释放内存)
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.发现镄循环了,不会用,而且ClearContinuous的参数只能是6好像
SysUtils,
Windows;type
PSBTNode = ^TSBTNode;
TSBTNode = record
count: Cardinal;
data: Cardinal;
size: Cardinal;
lch,rch: PSBTNode;
end; TSBT = class
private
// 节点数组
m_Buckets: array of PSBTNode;
// 节点数
NodeCount: Cardinal;
// 根节点,空节点
root,null: PSBTNode;
// 初始化
procedure NodeInit(ACount: Cardinal);
// 清除
procedure NodeClear;
// 左旋转
procedure lrotate(var x: PSBTNode); inline;
// 右旋转
procedure rrotate(var x: PSBTNode); inline;
// 保持性质
procedure maintain(var t: PSBTNode; const flag: Boolean); inline;
// 增加
procedure TreeAdd(var t: PSBTNode; v: PSBTNode); inline;
// 移除
function TreeRemove(var t: PSBTNode; var n: PSBTNode; v: Cardinal): Cardinal; inline;
// 返回第 x 大的元素
function TreeSelect(var t: PSBTNode; k: Cardinal): Cardinal; inline;
// 查找
function TreeFind(var t: PSBTNode; v: Cardinal): Boolean; inline;
// 排名
function TreeRank(var t: PSBTNode; v: Cardinal): Cardinal; inline;
// 向前,大
function TreeSucc(var t: PSBTNode; v: Cardinal): Cardinal; inline;
// 向后,小
function TreePred(var t: PSBTNode; v: Cardinal): Cardinal; inline;
public
constructor Create(ACount: Cardinal);
destructor Destroy; override;
procedure add(v: PSBTNode);
function remove(v: Cardinal): PSBTNode;
function select(k: Cardinal): Cardinal; inline;
function find(v: Cardinal): Boolean; inline;
function rank(v: Cardinal): Cardinal; inline;
function succ(v: Cardinal): Cardinal; inline;
function pred(v: Cardinal): Cardinal; inline;
function dwGet(N: Integer): Cardinal;
function dwRes(P: Cardinal): Boolean;
end;{ TSBT }
constructor TSBT.Create(ACount: Cardinal);
begin
NodeCount := 0;
new(null);
null^.data := 0;
null^.size := 0;
null^.lch := null;
null^.rch := null;
root := null;
NodeInit(ACount);
end;destructor TSBT.Destroy;
begin
NodeClear;
NodeCount := 0;
Dispose(null);
inherited Destroy;
end;procedure TSBT.NodeInit(ACount: Cardinal);
var
I: Integer;
begin
SetLength(m_Buckets, ACount);
for I := 0 to ACount-1 do
begin
New(m_Buckets[I]);
m_Buckets[I]^.data := I;
add(m_Buckets[I]);
end;
end;procedure TSBT.NodeClear;
var
I: Integer;
begin
for I := 0 to Length(m_Buckets)-1 do
begin
Dispose(m_Buckets[I]);
end;
end;procedure TSBT.lrotate(var x: PSBTNode);
var
y: PSBTNode;
begin
y := x^.rch;
x^.rch := y^.lch;
y^.lch := x;
y^.size := x^.size;
x^.size := x^.lch^.size+x^.rch^.size+1;
x := y;
end;procedure TSBT.rrotate(var x: PSBTNode);
var
y: PSBTNode;
begin
y := x^.lch;
x^.lch := y^.rch;
y^.rch := x;
y^.size := x^.size;
x^.size := x^.lch^.size+x^.rch^.size+1;
x := y;
end;procedure TSBT.maintain(var t: PSBTNode; const flag: Boolean);
begin
if t=null then
exit;
if not flag then
if t^.lch^.lch^.size>t^.rch^.size then
rrotate(t)
else if t^.lch^.rch^.size>t^.rch^.size then
begin
lrotate(t^.lch);
rrotate(t);
end
else
exit
else if t^.rch^.rch^.size>t^.lch^.size then
lrotate(t)
else if t^.rch^.lch^.size>t^.lch^.size then
begin
rrotate(t^.rch);
lrotate(t);
end
else
exit;
maintain(t^.lch, false);
maintain(t^.rch, true);
maintain(t, false);
maintain(t, true);
end;procedure TSBT.TreeAdd(var t: PSBTNode; v: PSBTNode);
begin
if t=null then
begin
t := v;
t^.count := 0;
t^.size := 1;
t^.lch := null;
t^.rch := null;
Inc(NodeCount);
end
else begin
inc(t^.size);
if v^.data<t^.data then
TreeAdd(t^.lch, v)
else
TreeAdd(t^.rch, v);
maintain(t, v^.data>=t^.data);
end;
end;function TSBT.TreeRemove(var t: PSBTNode; var n: PSBTNode; v: Cardinal): Cardinal;
var
tmp: PSBTNode;
begin
Result := Cardinal(-1);
if t=null then
Exit;
dec(t^.size);
if(v=t^.data) or ((v<t^.data) and (t^.lch=null)) or ((v>t^.data) and (t^.rch=null)) then
begin
Result := t^.data;
if(t^.lch=null) or (t^.rch=null) then
begin
if t^.lch=null then
begin
tmp := t;
t := tmp^.rch;
if tmp<>null then
begin
n := tmp;
Dec(NodeCount);
Exit;
end;
end;
if t^.rch=null then
begin
tmp := t;
t := tmp^.lch;
if tmp<>null then
begin
n := tmp;
Dec(NodeCount);
Exit;
end;
end;
end
else
t^.data := TreeRemove(t^.lch, n, t^.data+1);
end
else if v<t^.data then
Result := TreeRemove(t^.lch, n, v)
else
Result := TreeRemove(t^.rch, n, v);
end;function TSBT.TreeSelect(var t: PSBTNode; k: Cardinal): Cardinal;
begin
if (k=t^.lch^.size+1) then
begin
Result := t^.data;
exit;
end;
if k<=t^.lch^.size then
Result := TreeSelect(t^.lch, k)
else
Result := TreeSelect(t^.rch, k-1-t^.lch^.size);
end;function TSBT.TreeFind(var t: PSBTNode; v: Cardinal): Boolean;
begin
if t=null then
begin
Result := false;
exit;
end;
if v<t^.data then
Result := TreeFind(t^.lch,v)
else
Result := (v=t^.data) or TreeFind(t^.rch,v);
end;function TSBT.TreeRank(var t: PSBTNode; v: Cardinal): Cardinal;
begin
if t=null then
begin
Result := 1;
exit;
end;
if v<t^.data then
Result := TreeRank(t^.lch,v)
else
Result := t^.lch^.size+1+TreeRank(t^.rch,v);
end;function TSBT.TreeSucc(var t: PSBTNode; v: Cardinal): Cardinal;
var
tmp:Cardinal;
begin
if t=null then
begin
Result := v;
exit;
end;
if v>=t^.data then
Result := TreeSucc(t^.rch,v)
else
begin
tmp:=TreeSucc(t^.lch,v);
if tmp=v then
tmp := t^.data;
Result := tmp;
end;
end;function TSBT.TreePred(var t: PSBTNode; v: Cardinal): Cardinal;
var
tmp: Cardinal;
begin
if t=null then
begin
Result := v;
exit;
end;
if v<=t^.data then
Result := TreePred(t^.lch, v)
else
begin
tmp := TreePred(t^.rch,v);
if tmp=v then
tmp := t^.data;
Result := tmp;
end;
end;procedure TSBT.add(v: PSBTNode);
begin
TreeAdd(root, v);
end;function TSBT.remove(v: Cardinal): PSBTNode;
var
v2: Cardinal;
P: PSBTNode;
begin
Result := nil;
TreeRemove(root, Result, v);
v2 := Result^.data;
Result^.data := v;
//位置交换
P := m_Buckets[v2];
m_Buckets[v2] := m_Buckets[v];
m_Buckets[v] := P;
end;function TSBT.select(k: Cardinal): Cardinal;
begin
Result := TreeSelect(root, k);
end;function TSBT.find(v: Cardinal): Boolean;
begin
Result := TreeFind(root, v);
end;function TSBT.rank(v: Cardinal): Cardinal;
begin
Result := TreeRank(root, v);
end;function TSBT.succ(v: Cardinal): Cardinal;
begin
Result := TreeSucc(root, v);
end;function TSBT.pred(v: Cardinal): Cardinal;
begin
Result := TreePred(root, v);
end;function TSBT.dwGet(N: Integer): Cardinal;
var
M, D1, D2, NStart, NEnd: Integer;
P: PSBTNode;
begin
M := 1;
D2 := -1;
D1 := select(1);
if N<=1 then
begin
NStart := D1;
//移出使用中的对像
P := remove(NStart);
P^.count := 1;
Result := P^.data;
Exit;
end;
while True do
begin
//右旋转
D2 := succ(D1);
if D2=D1 then
Break;
if D2=D1+1 then
begin
Inc(M);
end
else
begin
M := 1;
end;
if M>=N then
Break;
D1 := D2;
end;
NStart := D2 - N + 1;
NEnd := NStart + N;
P := remove(NStart);
P^.count := N;
Result := P^.data;
Inc(NStart);
while NStart<NEnd do
begin
//移出使用中的对像
remove(NStart);
Inc(NStart);
end;
end;function TSBT.dwRes(P: Cardinal): Boolean;
var
M, N, NEnd: Cardinal;
begin
M := P;
// 页数
N := m_Buckets[M]^.count;
NEnd := M + N;
// 放回
while M<NEnd do
begin
add(m_Buckets[M]);
Inc(M);
end;
Result := True;
end;var
_SBT: TSBT;
I: Integer;
aaa: array of Cardinal;
n1,n2: Int64;begin
try
{ TODO -oUser -cConsole Main : Insert code here }
Writeln('初始化.');
QueryPerformanceCounter(n1);
_SBT := TSBT.Create(10000000);
QueryPerformanceCounter(n2);
Writeln('初始耗时:', (n2-n1) div 1000, 'ms');
Readln;
try
SetLength(aaa, 1000000);
//申请
Writeln('查找.');
Randomize;
QueryPerformanceCounter(n1);
for I := 0 to 999999 do
begin
aaa[I] := _SBT.dwGet(5);
end;
QueryPerformanceCounter(n2);
Writeln('查找耗时:', (n2-n1) div 1000, 'ms');
Readln;
//放回
Writeln('放回.');
QueryPerformanceCounter(n1);
for I := 0 to 999999 do
begin
_SBT.dwRes(aaa[I]);
end;
QueryPerformanceCounter(n2);
Writeln('放回耗时:', (n2-n1) div 1000, 'ms');
Readln;
finally
FreeAndNil(_SBT);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
2、可以快速清除指定组数的连续n个的数(注意,现在可以指定一次最多清除多少组了,以前是全部都清)
3、可以快速向数组添加任意多个数,并保持正确的顺序
4、可以快速查询某个数在数组中是否存在
5、可以快速查询某个数在最新的结果数组中的序号每个过程用过都不到0.1秒,甚至是远远不到0.1秒。
const
AllCount=10000000; //总的数据量
One_tenth=1000000; //十分之一//定义全局变量var
tmpData:pdword;
DataCount:dword; //每次清除后剩余的数据量
Data:array of dword; //存贮数据的数组
Clsed:array of dword; //存贮被清除的连续数的第一个数
ClsCnt:dword; //被清除的连续数的组数
//下面是8个功能函数:procedure initData; //分配内存,初始化数组
asm
pushad
mov eax,AllCount
mov DataCount,eax
push eax
shl eax,2
call sysgetmem
mov Data,eax
xor edx,edx
pop ecx
@p1:
inc edx
mov [eax],edx
add eax,4
loop @p1
mov eax,allCount
shl eax,2
call sysgetmem
mov tmpData,eax
mov edx,eax
mov eax,Data
mov ecx,allcount
shl ecx,2
call move
mov eax,allCount
shl eax,1
call sysgetmem
mov Clsed,eax
popad
end;procedure ClearOne_tenth; //随机清除十分之一的数据
asm
pushad
mov esi,tmpData
mov ecx,One_tenth
mov eax,AllCount
@p1:
push eax
push ecx
call random
pop ecx
shl eax,2
cmp dword ptr[esi+eax],0
jnz @p2
pop eax
jmp @p1
@p2:
mov dword ptr [esi+eax],0
pop eax
loop @p1
mov ecx,eax
mov eax,DataCount
sub eax,One_tenth
mov DataCount,eax
mov edi,Data
@p3:
cmp dword ptr[esi],0
jz @p4
mov edx,[esi]
mov [edi],edx
add edi,4
@p4:
add esi,4
loop @p3
popad
end;
procedure UpdateData; //更新临时内存中的数据至数组
asm
pushad
mov esi,tmpData
mov edi,Data
mov ecx,AllCount
xor eax,eax @p5:
cmp dword ptr[esi],0
jz @p6
mov edx,[esi]
mov [edi],edx
add edi,4
inc eax
@p6:
add esi,4
loop @p5
mov DataCount,eax
popad
end;
procedure ClearContinuous(LoopCnt,Cnt:dword); //清除Cnt个Loopcnt个连续的数据
var tmpcnt:dword;
asm
pushad
mov tmpcnt,edx
mov ecx,AllCount
dec ecx
mov esi,tmpData
mov edi,Clsed
xor edx,edx
inc edx
@p1:
mov ebx,[esi+4]
sub ebx,[esi]
cmp ebx,1
je @p2
xor edx,edx
@p2:
inc edx
cmp edx,eax
jne @p3
mov dword ptr[esi+4],0
pushad
sub esi,eax
sub esi,eax
sub esi,eax
sub esi,eax
add esi,8
mov edx,[esi]
mov [edi],edx
mov ecx,eax
dec ecx
@p4:
mov dword ptr[esi],0
add esi,4
loop @p4
popad
add edi,4
mov edx,tmpCnt
dec edx
mov tmpCnt,edx
cmp edx,0
jz @p7
xor edx,edx @p3:
add esi,4
loop @p1 @p7:
mov eax,clsed
sub edi,eax
shr edi,2
mov clscnt,edi call UpdateData
popad
end;
function NumberExists(num:dword):Bool; //查询指定的数是否存在
asm
push esi
mov esi,tmpData
shl eax,2
cmp dword ptr[esi+eax-4],0
jnz @p1
xor eax,eax
@p1:
pop esi
end;procedure AddNumber(num,cnt:dword); //添加从num开始的连续cnt个数
asm
push esi
mov esi,tmpdata
push eax
dec eax
shl eax,2
add esi,eax
pop eax
@p1:
cmp edx,0
jz @p2
mov [esi],eax
add esi,4
inc eax
dec edx
jmp @p1
@p2:
pop esi
end;function FindNumber(num:dword):dword; //查找指定的数在数组中的序号
asm
push esi
push ecx
mov esi,data
mov ecx,datacount
@p1:
cmp dword ptr[esi],eax
je @p2
add esi,4
loop @p1
@p2:
mov eax,esi
mov esi,data
sub eax,esi
shr eax,2
pop ecx
pop esi
end;procedure FreeData; //释放内存
asm
mov eax,tmpData
call sysfreemem
mov eax,Data
call sysfreemem
mov eax,clsed
call sysfreemem
xor eax,eax
mov DataCount,eax
mov ClsCnt,eax
mov Data,eax
mov clsed,eax
end;使用示例:
var old1,old2,old3:dword;
i:integer;
begin
randomize;
old1:=gettickcount;
initData; //初始化数据
old1:=gettickcount-old1;
old2:=gettickcount;
ClearOne_tenth; //随机清除十分之一的数据
old2:=gettickcount-old2;
old3:=gettickcount;
ClearContinuous(6,99999); //快速从剩余的数中查找出连续6个的数并清除前99999组
old3:=gettickcount-old3; showmessage(format('初始化数组用时:%d 毫秒,清除十分之一用时:%d 毫秒'+#13+#10
+'清除连续6个的数用时:%d 毫秒'+#13+#10+'最后剩余数字量:%d'
+#13+#10+'被清除的组数:%d',[old1,old2,old3,DataCount,ClsCnt])); old1:=gettickcount;
//下面三行代码重新将被清除的数添加回去
for i := 0 to ClsCnt-1 do
addnumber(clsed[i],6); updatedata; //添加完所有需要添加的数据后,要执行一次updatedata函数 old1:=gettickcount-old1; showmessage(format('重新添加数据用时:%d 毫秒',[old1])); if numberexists(999999) then
showmessage(format('999999在结果数组中的序号为:%d'
+#13+#10+'验证结果,Data[%d]=%d',[findnumber(999999),findnumber(999999),Data[findnumber(999999)]]))
else
showmessage('999999已被清除,在结果数组中不存在!');
// freedata; //释放内存(如果要继续清除,就暂时不要释放内存)
unit uVirtualMemPool;interfaceuses
SysUtils, Windows;type
TVirtualMemPool = class; PSBTNode = ^TSBTNode;
TSBTNode = record
IsUse: Boolean; //是否使用中
count: Cardinal; //使用页数
value: Pointer; //内存地址
data: Cardinal; //节点序号
size: Cardinal; //子节点数
lch,rch: PSBTNode; //左右节点
end; // 平衡二叉查找树SBT
TSizeBalancedTree = class
private
VMPool: TVirtualMemPool;
// 节点数
NodeCount: Cardinal;
// 根节点,空节点
root,null: PSBTNode;
// 左旋转
procedure lrotate(var x: PSBTNode); inline;
// 右旋转
procedure rrotate(var x: PSBTNode); inline;
// 保持性质
procedure maintain(var t: PSBTNode; const flag: Boolean); inline;
// 增加
procedure TreeAdd(var t: PSBTNode; v: PSBTNode); inline;
// 移除
function TreeRemove(var t: PSBTNode; var n: PSBTNode; v: Cardinal): Cardinal; inline;
// 返回第 x 大的元素
function TreeSelect(var t: PSBTNode; k: Cardinal): Cardinal; inline;
// 查找
function TreeFind(var t: PSBTNode; v: Cardinal): Boolean; inline;
// 排名
function TreeRank(var t: PSBTNode; v: Cardinal): Cardinal; inline;
// 向前,大
function TreeSucc(var t: PSBTNode; v: Cardinal): Cardinal; inline;
// 向后,小
function TreePred(var t: PSBTNode; v: Cardinal): Cardinal; inline;
public
constructor Create(AVMpool: TVirtualMemPool);
destructor Destroy; override;
procedure add(v: PSBTNode);
function remove(v: Cardinal): PSBTNode;
function select(k: Cardinal): Cardinal; inline;
function find(v: Cardinal): Boolean; inline;
function rank(v: Cardinal): Cardinal; inline;
function succ(v: Cardinal): Cardinal; inline;
function pred(v: Cardinal): Cardinal; inline;
end; // 内存管理
TVirtualMemPool = class
public
m_VMLock: TRTLCriticalSection;
m_NMLock: TRTLCriticalSection;
m_PageSize: Cardinal;
m_Count: Cardinal;
m_lpBase: Pointer;
m_Buckets: array of PSBTNode;
m_SBTStorage: TSizeBalancedTree;
private
function GetCount: Cardinal;
function GetUseCount: Cardinal;
function GetFreeCount: Cardinal;
procedure InitMemPool(ACount: Integer);
procedure Clear;
public
property Count: Cardinal read GetCount;
property UseCount: Cardinal read GetUseCount;
property FreeCount: Cardinal read GetFreeCount;
public
constructor Create(ACount: Integer);
destructor Destroy; override;
public
function VMAlloc(dwSize: Cardinal; IsLock: Boolean = True): Pointer;
function VMReAlloc(var P; dwSize: Cardinal): Pointer;
function VMFree(var P; IsLock: Boolean = True): Boolean;
end;implementation
constructor TSizeBalancedTree.Create(AVMpool: TVirtualMemPool);
begin
VMPool := AVMpool;
NodeCount := 0;
new(null);
null^.data := 0;
null^.size := 0;
null^.lch := null;
null^.rch := null;
root := null;
end;destructor TSizeBalancedTree.Destroy;
begin
NodeCount := 0;
Dispose(null);
inherited Destroy;
end;procedure TSizeBalancedTree.lrotate(var x: PSBTNode);
var
y: PSBTNode;
begin
y := x^.rch;
x^.rch := y^.lch;
y^.lch := x;
y^.size := x^.size;
x^.size := x^.lch^.size+x^.rch^.size+1;
x := y;
end;procedure TSizeBalancedTree.rrotate(var x: PSBTNode);
var
y: PSBTNode;
begin
y := x^.lch;
x^.lch := y^.rch;
y^.rch := x;
y^.size := x^.size;
x^.size := x^.lch^.size+x^.rch^.size+1;
x := y;
end;procedure TSizeBalancedTree.maintain(var t: PSBTNode; const flag: Boolean);
begin
if t=null then
exit;
if not flag then
if t^.lch^.lch^.size>t^.rch^.size then
rrotate(t)
else if t^.lch^.rch^.size>t^.rch^.size then
begin
lrotate(t^.lch);
rrotate(t);
end
else
exit
else if t^.rch^.rch^.size>t^.lch^.size then
lrotate(t)
else if t^.rch^.lch^.size>t^.lch^.size then
begin
rrotate(t^.rch);
lrotate(t);
end
else
exit;
maintain(t^.lch, false);
maintain(t^.rch, true);
maintain(t, false);
maintain(t, true);
end;procedure TSizeBalancedTree.TreeAdd(var t: PSBTNode; v: PSBTNode);
begin
if t=null then
begin
t := v;
//进入的内存设置为未使用
t^.IsUse := False;
t^.count := 0;
t^.size := 1;
t^.lch := null;
t^.rch := null;
Inc(NodeCount);
end
else begin
inc(t^.size);
if v^.data<t^.data then
TreeAdd(t^.lch, v)
else
TreeAdd(t^.rch, v);
maintain(t, v^.data>=t^.data);
end;
end;function TSizeBalancedTree.TreeRemove(var t: PSBTNode; var n: PSBTNode; v: Cardinal): Cardinal;
var
tmp: PSBTNode;
begin
Result := Cardinal(-1);
if t=null then
Exit;
dec(t^.size);
if(v=t^.data) or ((v<t^.data) and (t^.lch=null)) or ((v>t^.data) and (t^.rch=null)) then
begin
Result := t^.data;
if(t^.lch=null) or (t^.rch=null) then
begin
if t^.lch=null then
begin
tmp := t;
t := tmp^.rch;
if tmp<>null then
begin
n := tmp;
Dec(NodeCount);
Exit;
end;
end;
if t^.rch=null then
begin
tmp := t;
t := tmp^.lch;
if tmp<>null then
begin
n := tmp;
Dec(NodeCount);
Exit;
end;
end;
end
else
t^.data := TreeRemove(t^.lch, n, t^.data+1);
end
else if v<t^.data then
Result := TreeRemove(t^.lch, n, v)
else
Result := TreeRemove(t^.rch, n, v);
end;function TSizeBalancedTree.TreeSelect(var t: PSBTNode; k: Cardinal): Cardinal;
begin
if (k=t^.lch^.size+1) then
begin
Result := t^.data;
exit;
end;
if k<=t^.lch^.size then
Result := TreeSelect(t^.lch, k)
else
Result := TreeSelect(t^.rch, k-1-t^.lch^.size);
end;function TSizeBalancedTree.TreeFind(var t: PSBTNode; v: Cardinal): Boolean;
begin
if t=null then
begin
Result := false;
exit;
end;
if v<t^.data then
Result := TreeFind(t^.lch,v)
else
Result := (v=t^.data) or TreeFind(t^.rch,v);
end;function TSizeBalancedTree.TreeRank(var t: PSBTNode; v: Cardinal): Cardinal;
begin
if t=null then
begin
Result := 1;
exit;
end;
if v<t^.data then
Result := TreeRank(t^.lch,v)
else
Result := t^.lch^.size+1+TreeRank(t^.rch,v);
end;function TSizeBalancedTree.TreeSucc(var t: PSBTNode; v: Cardinal): Cardinal;
var
tmp:Cardinal;
begin
if t=null then
begin
Result := v;
exit;
end;
if v>=t^.data then
Result := TreeSucc(t^.rch,v)
else
begin
tmp:=TreeSucc(t^.lch,v);
if tmp=v then
tmp := t^.data;
Result := tmp;
end;
end;function TSizeBalancedTree.TreePred(var t: PSBTNode; v: Cardinal): Cardinal;
var
tmp: Cardinal;
begin
if t=null then
begin
Result := v;
exit;
end;
if v<=t^.data then
Result := TreePred(t^.lch, v)
else
begin
tmp := TreePred(t^.rch,v);
if tmp=v then
tmp := t^.data;
Result := tmp;
end;
end;procedure TSizeBalancedTree.add(v: PSBTNode);
begin
TreeAdd(root, v);
end;function TSizeBalancedTree.remove(v: Cardinal): PSBTNode;
var
v2: Cardinal;
C: Pointer;
P: PSBTNode;
begin
Result := nil;
TreeRemove(root, Result, v);
v2 := Result^.data;
Result^.data := v;
//移出的内存设置为使用
Result^.IsUse := True;
//value交换
C := VMPool.m_Buckets[v2]^.value;
VMPool.m_Buckets[v2]^.value := VMPool.m_Buckets[v]^.value;
VMPool.m_Buckets[v]^.value := C;
//位置交换
P := VMPool.m_Buckets[v2];
VMPool.m_Buckets[v2] := VMPool.m_Buckets[v];
VMPool.m_Buckets[v] := P;
end;function TSizeBalancedTree.select(k: Cardinal): Cardinal;
begin
Result := TreeSelect(root, k);
end;function TSizeBalancedTree.find(v: Cardinal): Boolean;
begin
Result := TreeFind(root, v);
end;function TSizeBalancedTree.rank(v: Cardinal): Cardinal;
begin
Result := TreeRank(root, v);
end;function TSizeBalancedTree.succ(v: Cardinal): Cardinal;
begin
Result := TreeSucc(root, v);
end;function TSizeBalancedTree.pred(v: Cardinal): Cardinal;
begin
Result := TreePred(root, v);
end;
constructor TVirtualMemPool.Create(ACount: Integer);
var
SysInfo: TSystemInfo;
begin
inherited Create;;
InitializeCriticalSection(m_VMLock);
InitializeCriticalSection(m_NMLock);
GetSystemInfo(SysInfo);
m_PageSize := SysInfo.dwPageSize;
m_SBTStorage := TSizeBalancedTree.Create(Self);
m_Count := ACount;
InitMemPool(m_Count);
end;destructor TVirtualMemPool.Destroy;
begin
FreeAndNil(m_SBTStorage);
Clear;
VirtualFree(m_lpBase, 0, MEM_RELEASE);
DeleteCriticalSection(m_NMLock);
DeleteCriticalSection(m_VMLock);
inherited Destroy;
end;function TVirtualMemPool.GetCount: Cardinal;
begin
Result := m_Count;
end;function TVirtualMemPool.GetUseCount: Cardinal;
begin
EnterCriticalSection(m_NMLock);
try
Result := m_Count - m_SBTStorage.NodeCount;
finally
LeaveCriticalSection(m_NMLock);
end;
end;function TVirtualMemPool.GetFreeCount: Cardinal;
begin
EnterCriticalSection(m_NMLock);
try
Result := m_SBTStorage.NodeCount;
finally
LeaveCriticalSection(m_NMLock);
end;
end;procedure TVirtualMemPool.InitMemPool(ACount: Integer);
var
I: Integer;
begin
EnterCriticalSection(m_VMLock);
try
// 申请大块内存
m_lpBase := VirtualAlloc(nil,
ACount*m_PageSize,
MEM_RESERVE,
PAGE_NOACCESS);
SetLength(m_Buckets, ACount);
//debug('m_lpBase: %d, NumberOfNode: %d', [Cardinal(m_lpBase), NumberOfNode]);
for I := 0 to ACount-1 do
begin
{ 为第I页地址提交内存。 }
New(m_Buckets[I]);
m_Buckets[I]^.data := I;
m_Buckets[I]^.value := VirtualAlloc(Pointer(Cardinal(m_lpBase)+(I*m_PageSize)),
m_PageSize,
MEM_COMMIT,
PAGE_READWRITE);
//debug('I: %d=%d', [I, Cardinal(m_Buckets[I]^.value)]);
//ZeroMemory(m_Buckets[I]^.value, m_PageSize);
m_SBTStorage.add(m_Buckets[I]);
end;
finally
LeaveCriticalSection(m_VMLock);
end;
end;procedure TVirtualMemPool.Clear;
var
I: Integer;
begin
EnterCriticalSection(m_VMLock);
try
for I := 0 to Length(m_Buckets)-1 do
begin
Dispose(m_Buckets[I]);
end;
finally
LeaveCriticalSection(m_VMLock);
end;
end;function TVirtualMemPool.VMAlloc(dwSize: Cardinal; IsLock: Boolean = True): Pointer;
var
N, M, D1, D2, NStart, NEnd: Integer;
P: PSBTNode;
begin
if FreeCount<=0 then
begin
Result := nil;
raise Exception.Create('No free pages in main memory.');
Exit;
end;
if IsLock then EnterCriticalSection(m_VMLock);
try
N := dwSize div m_PageSize;
if (dwSize mod m_PageSize)<>0 then
Inc(N);
M := 1;
D2 := -1;
D1 := m_SBTStorage.select(1);
if N<=1 then
begin
NStart := D1;
//移出使用中的对像
P := m_SBTStorage.remove(NStart);
P^.count := 1;
Result := P^.value;
Exit;
end;
while True do
begin
//右旋转
D2 := m_SBTStorage.succ(D1);
if D2=D1 then
Break;
if D2=D1+1 then
begin
Inc(M);
end
else
begin
M := 1;
end;
if M>=N then
Break;
D1 := D2;
end;
NStart := D2 - N + 1;
NEnd := NStart + N;
P := m_SBTStorage.remove(NStart);
P^.count := N;
Result := P^.value;
Inc(NStart);
while NStart<NEnd do
begin
m_SBTStorage.remove(NStart);
Inc(NStart);
end;
finally
if IsLock then LeaveCriticalSection(m_VMLock);
end;
end;function TVirtualMemPool.VMReAlloc(var P; dwSize: Cardinal): Pointer;
var
OldN, M, NewN, NEnd: Cardinal;
NewP: Pointer;
begin
Result := nil;
if Pointer(P)=nil then
begin
Result := VMAlloc(dwSize);
Exit;
end;
EnterCriticalSection(m_VMLock);
try
M := (Cardinal(Pointer(P))-Cardinal(m_lpBase)) div m_PageSize;
// 原页数
OldN := m_Buckets[M]^.count;
// 新页数
NewN := dwSize div m_PageSize;
if (dwSize mod m_PageSize)<>0 then
Inc(NewN);
// 新页数=原页数
if NewN=OldN then
begin
Result := Pointer(P);
end
// 新页数<原页数,多余的页放回页表
else if NewN<OldN then
begin
NEnd := M + OldN;
m_Buckets[M]^.count := OldN-NewN;
M := M + NewN;
while M<NEnd do
begin
m_SBTStorage.add(m_Buckets[M]);
Inc(M);
end;
Result := Pointer(P);
end
// 新页数>原页数,重新申请并Copy原数据到新数据
else if NewN>OldN then
begin
NewP := VMAlloc(dwSize, False);
//原数据Copy到新数据中
if NewP<>nil then
CopyMemory(NewP, Pointer(P), OldN*m_PageSize);
//放回原页数
VMFree(P, False);
//返回
Pointer(P) := NewP;
Result := NewP;
end;
finally
LeaveCriticalSection(m_VMLock);
end;
end;function TVirtualMemPool.VMFree(var P; IsLock: Boolean = True): Boolean;
var
M, N, NEnd: Cardinal;
begin
if IsLock then EnterCriticalSection(m_VMLock);
try
M := (Cardinal(Pointer(P))-Cardinal(m_lpBase)) div m_PageSize;
Pointer(P) := nil;
// 页数
N := m_Buckets[M]^.count;
NEnd := M + N;
// 放回
while M<NEnd do
begin
m_SBTStorage.add(m_Buckets[M]);
Inc(M);
end;
finally
if IsLock then LeaveCriticalSection(m_VMLock);
end;
Result := True;
end;end.//使用方法
var
VMP: TVirtualMemPool;
P: PAnsiChar;
S: AnsiString;
begin
VMP := TVirtualMemPool.Create(200000);
try
//分配
P := VMP.VMAlloc(4096*3);
Writeln(Cardinal(P));
S := 'ABCDEFG';
CopyMemory(P, @S[1], Length(S));
FillChar(P^, 4096*3, 88);
//重新分配
P := VMP.VMReAlloc(P, 4096*6);
Writeln(Cardinal(P));
//回收
VMP.VMFree(P);
if P=nil then
Writeln('OK');
Readln;
finally
FreeAndNil(VMP);
end;
end;//我这里是按页大小分配的,页大小4096,如果分配3页就是4096*3,相当于,查找3个连续的数!希望cngst大哥帮我看看,或有其他高手提供好的算法!
非常感谢cngst大哥和上面的各位高手,这个贴子完成后是不是可以推荐到首页呢?
TSBTNode = record
IsUse: Boolean; //是否使用中
count: Cardinal; //使用页数
value: Pointer; //内存地址
data: Cardinal; //节点序号
size: Cardinal; //子节点数
lch,rch: PSBTNode; //左右节点
end;
最主要的是
value: Pointer; //内存地址
data: Cardinal; //节点序号
这个data就是现在的数组了,value就是记录的地址,是以4096递加的主要就是分配
VMAlloc(内存大小)
内存大小 div 4096 = 连续的页数,就是连续n个数
分配连续n页的内存,返回value,就是内存地址
VMReAlloc(内存大小)
根据内存大小计算出所需页,如果所需页=以前的页数,则直接返回,如果所需的页小于以前的页,则把多余的页放回原队列,如果所需的页大于以前的面,则重新分配,并copy原value里的内存到新申请的value的内存里,然后把原来申请的放回队列中VMFree就是根据原来的value计算出数组的ID
,因为所有value都是有规律的,4096递加,并且有个基地址lpBase
所以
数组id = (现在用的value-lpBase) div 4096;得到这个数据id了,就得到了这个节点,也得到了申请的页数PSBTNode.count根据页数放回连续的页到队列中
AllCount=10000000; //总的数据量
One_tenth=1000000; //十分之一//定义全局变量var
tmpData:pdword;
DataCount:dword; //每次清除后剩余的数据量
Data:array of dword; //存贮数据的数组
Clsed:array of dword; //存贮被清除的连续数的第一个数
ClsCnt:dword; //被清除的连续数的组数
//下面是8个功能函数:procedure initData; //分配内存,初始化数组
asm
pushad ; EAX,ECX,EDX,EBX,ESP,EBP,ESI和EDI全部压栈
mov eax,AllCount ; EAX = AllCount(即1亿)
mov DataCount,eax ; DataCount = EAX, 跟上面合起来 DataCount = AllCount
push eax ; EAX压栈(1亿的值)
shl eax,2 ; EAX左移两位, 即1亿 = 0x0098 9680 << 2 = 4亿.
call sysgetmem ; EAX为第一参数呼叫系统内存分配函数, 返回地址值在EAX
mov Data,eax ; Data被分配给指向4亿个BYTE的空间,共计即Data[10000000]
xor edx,edx ; 清空EDX
pop ecx ; ECX为EAX之前的压栈值, 1亿
@p1:
inc edx ; EDX++(从0开始)
mov [eax],edx ; *Data = EDX
add eax,4 ; Data地址移拉下一个, 即@DWORD[0] 变成@DWORD[4]
loop @p1 ; 循环1亿次, 即Data[]按顺序写入1~1亿的值
mov eax,allCount ; EAX = 1亿
shl eax,2 ; EAX = 4亿
call sysgetmem ; 分配4亿个BYTE
mov tmpData,eax ; tmpData = tmpData[10000000]
mov edx,eax ; EDX = tmpData
mov eax,Data ; Data地址赋值到EAX
mov ecx,allcount ; ECX = 1亿
shl ecx,2 ; ECX = 4亿
call move ; Move(const Source;var Dest; Count: Integer); 即Move(Data, tmpData, 4亿)
mov eax,allCount ; EAX = 1亿
shl eax,1 ; EAX = 2亿
call sysgetmem ; 分配2亿个BYTE的空间
mov Clsed,eax ; Clsed = DWORD[2亿/4];(2亿个BYTE)
popad ; EAX,ECX,EDX,EBX,ESP,EBP,ESI和EDI全部压栈
end;即上述代码等效的功能: Data = Getmem(AllCount * 4);
for(i=0 to AllCount - 1)
Data[i] = i + 1;
tmpData = Getmem(AllCount * 4);
Move(Data, tmpData, AllCount * 4);
Clsed = Getmem( AllCount div 2);
汇编上拆分没错的话, 代码就是这样了. 我想楼主应该想得到剩下的处理步骤了.
Data = Getmem(AllCount * 4);
1亿个DWORD?
以前没这么用过,看来要学的东西不少啊
Clsed = Getmem( AllCount div 2);
另外如果我要初始化一个结构体数组也能用这样的方法吗?
或者, 理解成是 Data = Getmem(AllCount * SizeOf(DWORD)) 吧, 这样就好理解了吧..
用上超大数组来映射, 肯定会快的, 只是内存空间利用率低下而已, 想要快, 又要速度高, 可以考虑采用bit来标识的, 运算是多一点, 但都是多两三条CPU指令, 不会对速度有多大影响的. 即1亿的数据, 只要采用1亿/32个DWORD来记录就可以了. 因为一个DWORD有32位.