无穷大数组上如何直接寻址来实现字典?

   这是算法导论习题11.1-4。
   具体题目如下:
   
     
   解决该题目的要点:
   1.由于是无穷大的数组,所以无法事先初始化该数组。
   2.所提供的方案必须是O(1)。
   3.使用的额外空间只能是O(n),这样平均到每一个项上的空间都是O(1)。

   一时之间好像没有一点头绪,在几个群里面发问了,网上搜了很久也没有找到答案,后面一群里有个高人给了个链接,里面有解法。
链接地址:http://www.cnblogs.com/flyfy1/archive/2011/03/05/1971502.html,这篇文章里面另外给了个pdf,这个pdf估计是解法
的来源。伪代码写得不给力,不过前面的英文描述却很清晰。说实话,这个方法很巧妙。

   解法大概的意思如下:
   开一个额外的数组A,A[0]表示A数组元素的数目(当然不包括A[0]本身),A[i]代表插入的第i个元素的key。假设原来的无穷大数组用Huge
表示,如果Huge[i](直接寻址,假设i就是key)有效,则表示其在A数组中的索引。那么如果A[Huge[i]] == i 而且 Huge[i] <= A[0] &&
Huge[i] > 0,则表示i这个位置已经有元素插入了。

   插入:A[0]++;A[A[0]] = key; Huge[key] = A[0];
   搜索:  A[Huge[i]] == i && Huge[i] <= A[0] && Huge[i] > 0 则return true;
   删除:  先搜索该位置是否有元素, 如果Search(key)成功,则先把Huge[ A[A[0]] ] = Huge[key],
            然后交换A[A[0]]和A[Huge[key]],A[0]--即可。
   所有操作都是O(1),平均到每一个项,使用的空间都是O(1)。

   我用代码实现的模拟如下:
#include <stdio.h>
#include <vector>
#include <algorithm>
using std::swap;
using std::vector;
#define INF (100)

int nHuge[INF];//假设这个巨大的数组是无法初始化的
vector<int> vA;

void Init()
{
    vA.push_back(0);//添加A[0]表示元素的数目
}

void Insert(int nKey)
{
    vA[0]++;
    nHuge[nKey] = vA[0];
    vA.push_back(nKey);
}

bool Search(int nKey)
{
    if (nHuge[nKey] > 0 && nHuge[nKey] <= vA[0] && vA[nHuge[nKey]] == nKey)
    {
        return true;
    }

    return false;
}

void Delete(int nKey)
{
    if (Search(nKey))
    {
        nHuge[ vA[vA[0]] ] = nHuge[nKey];//将huge的最后一个元素中存储的A数组的索引改为nHuge[nKey]
        swap(vA[vA[0]], vA[nHuge[nKey]]);//交换key
        --vA[0];
        vA.erase(vA.end() - 1);
    }
}

#define MAX (10)
int main()
{
    Init();
    int i;
    for (i = 0; i < MAX; ++i)
    {
        Insert(i);
    }
    for (i = 0; i < MAX; ++i)
    {
        printf("Search:%d %s\n", i, Search(i) == true? "Success" : "Failure");
    }
    printf("\n");

    Delete(4);
    Delete(9);
    Delete(1);
    for (i = 0; i < MAX * 2; ++i)
    {
        printf("Search:%d %s\n", i, Search(i) == true? "Success" : "Failure");
    }

    return 0;
}

posted on 2012-03-20 19:26 yx 阅读(1383) 评论(7)  编辑 收藏 引用 所属分类: 数据结构

评论

# re: 无穷大数组上如何直接寻址来实现字典? 2012-03-21 10:38 zhongshan.li

void Delete(int nKey)
{
if (Search(nKey))
{
nHuge[ vA[vA[0]] ] = nHuge[nKey];//将huge的最后一个元素中存储的A数组的索引改为nHuge[nKey]
swap(vA[vA[0]], vA[nHuge[nKey]]);//交换key
--vA[0];
}
}

没有erase vA 中最后一个元素  回复  更多评论   

# re: 无穷大数组上如何直接寻址来实现字典? 2012-03-21 16:12 远行

vA[0]--就可以表示删除了,至于删除这点内存就没必要了,哦,没想清楚,确实应该erase,因为Insert的时候是push_back的@zhongshan.li
  回复  更多评论   

# re: 无穷大数组上如何直接寻址来实现字典? 2012-03-24 10:02 泡菜

说实话,是被标题吸引进来的---无穷大数组
是个神马东东哦???
C/C++规定数组形式为X[int]。。。。int无穷木?

具体代码没看,看着头痛。。。老年人都这样  回复  更多评论   

# re: 无穷大数组上如何直接寻址来实现字典? 2012-03-24 13:05 远行

说的很清楚,算法导论习题,代码前面有算法解释,敢问你有多老了。。。@泡菜
  回复  更多评论   

# re: 无穷大数组上如何直接寻址来实现字典? 2012-03-24 17:29 泡菜

老得字看不清楚老。。。。

在Win下默认堆栈为1M;Linux下一般为8~10M。。。。

介个、介个。。。默认状况就能无穷了哇  回复  更多评论   

# re: 无穷大数组上如何直接寻址来实现字典? 2012-03-24 20:20 远行

那你继续老你的吧@泡菜
  回复  更多评论   

# re: 无穷大数组上如何直接寻址来实现字典? 2012-03-24 22:12 泡菜

就木考虑在AIX系统上用介段代码?介个AIX默认堆栈为60多M

俺决定老。。。为了抵抗衰老
回家一定多吃菠菜,多补充A~Z的维生素。。。争取早日回到人民的大怀抱中  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2012年3月>
26272829123
45678910
11121314151617
18192021222324
25262728293031
1234567

导航

统计

公告

常用链接

留言簿(3)

随笔分类

随笔档案

me

好友

同学

网友

搜索

最新评论

阅读排行榜

评论排行榜