我有一个从1到10000000的数首先随机从中抽掉十分之一的数然后我需要一个算法,快速从剩余的数中查找出连续n个的数,比如5-10,连续6个的数(n是不固定的),
查找出来后立即移除出这些数,然后再进行查找

解决方案 »

  1.   

    比如5-10,连续6个的数(n是不固定的)
    你给它拼成一个字符串, 然后做字符串查找就行了, KMP算法和DELPHI自带的POSEX都可以 
      

  2.   

    而且那个pos的字符串查找也是循环的,拿到这里用效率不怎么高的,我自己写的pos都比delphi自带的pos要快
      

  3.   

    临时给楼主写了几个函数,我是这样处理结果的:
    比如有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秒。如果不需要重新排列数字,保持数字原来在数据中的位置,速度还可以快很多。
      

  4.   

    谢谢cngst大哥,不过asm小弟实在看不明白啊!而且你的算法中貌似用了一个大循环啊,其实那点儿机清除不重要我要的算法就是你的ClearContinuous的能力,另外要返回这几个连续数的头一个数另外问一下cngst大哥,有没有学习asm的好办法?
      

  5.   


    稍作修改,加了一个数组: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;  //释放内存(如果要继续清除,就暂时不要释放内存)
      

  6.   

    cngst大哥能帮忙改成delphi的吗?汇编实在玩不了,我主要是想学习下算法!
      

  7.   

    其实这个最终的应用就是对页式内存表的操作,那个随机可以不要,只是为了模拟出已经被分配出去的内存,
    只有那个从页表内查找n个连续的页并将这几个页从页表中移除(或设置为已使用),这n个连续的页使用完成后再按页的序号插入原页表队列中去,供下次使用另外cngst大哥能帮忙改成delphi的吗?你那个asm我只能看懂mov xor call之类的东西,过程的n-m参数是哪个寄存器我都不明白
      

  8.   

    我有一个从1到10000000的数array of [0..10000000-1] of Byte;最开始进入时,全部空闲,都设置为1,  被使用后,设置为0,判断连续的n个数,遍历比较n DIV 4个整数如果是$1111然后比较之后的(n and 3)个Byte,如果都是1,即得到连续的n个数,数字就是序号
      

  9.   

    更正一下:
    是遍历比较n DIV 4个整数如果是$01010101,
    (n shl 2)更好些
      

  10.   

    假设已经使用了前面的9000000个,需要移动后面1000000到最前面,这个移动过程,耗时相信也不会少,每使用一次,都要移动后面的数据,当内存释放的时候,还得把数据插回去,这个又是大面积移动,如果是内存管理,那多线程下,只有使用全局锁,而且是缩整个列表,而不能使用 lock xchg , lock xadd,等指令了
      

  11.   


    貌似用一个双向链表倒是可以快不少,但我相信查询移出和插入肯定还有更快的算法!不知道哪位高手能给点思路另外我看asm和看天书没两样
      

  12.   

    n是不固定的?
    我这样实现不知道速度怎么样
    假设n=5
    那么你就用折半的办法 首先10000个数的1-5个数先取出, 假设1-5的数是 6 5 7 8 9 首先判断 7的前两位是否是5(7-2) 不是的话判断后面的数是不是9(7+2) 如果是的话继续判断9的后面是不是11(9+2)
    如果你n多的话建议用这个办法
      

  13.   

    楼主会不会分裂链表, 应该是会的吧..
    1到1亿里面, 随机抽取10分一的数走, 每次抽取, 总是抽了一次以后就不能抽走吧..
    那么首先, 在链表里面只有1个结点.
    List: 
      Node1->1 ~ 1亿.
    从里面抽掉了一个数, 例如9, 那么链表就变成:
    List:
      Node1->1 ~ 8
      Node2->10 ~ 1亿.
    如此类推, 抽走10份之一的数走了, 那么链表最坏的情况是被拆开1亿/10那么多份, 但也有可能只分成为两份, 最终要看抽取的数据是在每个结点范围的内的值还是结点范围的边界值而定, 边界值是不需要分分分裂的.有了这样的一个链表...我想剩下怎样去掉任意连续长度的块..很容易了吧...
    假如分裂的结点是带有内存池方式, 会分裂得更快. 1亿以内的运算, 现在家用电脑也不成问题了, 保证清除时快于0.1S, 每个结点从头到尾都有最大值和最小值, 并且是肯定连续的, 取余运算, 直接就得到当前的块能够乘余哪个段了. 小于nCnt则直接跳过.
      

  14.   


    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好像
      

  15.   

    ClearContinuous的参数只要大于1就行了,并不局限为6。9000000个数的情况下,清除所有连续6个数,单次执行不到0.1秒,如果去除内存拷贝过程、清除完后将数重新排列的过程,单次执行不到0.05秒。其实算法并不高明。连续执行99999次的话,那就要很长很长的时间了。
      

  16.   

    贴一下我的代码,我感觉我这个效率一般,请各位路过的大哥帮忙看看能不能优化,或给出其他算法!主要是查询出来后原要放回原来的队列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.
      

  17.   

    另外,我是一次执行就全部清除,并不是一次清除一个,如果不是为了计时,只为清除99999组的话,没必要执行99999次,它一次就全部清除了。清除后的数存在Data数组中,并已重新排列好,被清除的数的第一个数存在clsed数组中,DataCount是清除后剩余数的量,clscnt是被清除的组数。
      

  18.   

    只是使用的话,不需要看懂asm(不过其实楼主说过能看懂mov、xor、call等,这足够了,耐心点一行行看,能懂的)。如果实际使用的话,先执行一次初始化函数(主要为分配内存),然后想自定义数据(如果不要它初始化的数据)的话,只需要将数据都依次存放在Data数组中,并设置DataCount的值,再执行ClearContinuous就行了。
      

  19.   

    再次改进了一下代码,现在可以完整的实现楼主所有的要求了1、可以随机清除十分之一的数
    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;  //释放内存(如果要继续清除,就暂时不要释放内存)
      

  20.   

    最后再请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
      

  21.   

    { 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;
      

  22.   

    { 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大哥和上面的各位高手,这个贴子完成后是不是可以推荐到首页呢?
      

  23.   

    已将程序源代码打包上传,可以在:http://download.csdn.net/source/3452389下载。
      

  24.   

    其实不用看代码的,最终的目前就是操作那个结构体  PSBTNode = ^TSBTNode;
       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根据页数放回连续的页到队列中
      

  25.   

    让我们一起分析汇编吧. 算法, 通过只要知道初始化的过程, 就会知道大概的做法是怎样的了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                   ; 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);
    汇编上拆分没错的话, 代码就是这样了. 我想楼主应该想得到剩下的处理步骤了.
      

  26.   

    可以直接分配数组的内存啊?
    Data = Getmem(AllCount * 4);
    1亿个DWORD?
    以前没这么用过,看来要学的东西不少啊
      

  27.   

    另外为什么
    Clsed = Getmem( AllCount div 2);
      

  28.   

    popad是出栈吧?
    另外如果我要初始化一个结构体数组也能用这样的方法吗?
      

  29.   

    为什么不能这样用啊...4个BYTE合成一个DWORD, 那么分配8个BYTE就是两个DWORD, 有什么不行的?
    或者, 理解成是 Data = Getmem(AllCount * SizeOf(DWORD)) 吧, 这样就好理解了吧..
    用上超大数组来映射, 肯定会快的, 只是内存空间利用率低下而已, 想要快, 又要速度高, 可以考虑采用bit来标识的, 运算是多一点, 但都是多两三条CPU指令, 不会对速度有多大影响的. 即1亿的数据, 只要采用1亿/32个DWORD来记录就可以了. 因为一个DWORD有32位.