用多级链表实现对链表的折半查找

lembo520390 2008-07-30 04:43:25
在链表描述的具有length个元素的集合中进行搜索,至多需要length次访问节点。如果在链的中部节点加一个指针,并记录头部到中部的距离,则访问的节点数可以减少到n/2+1次。搜索时,首先将欲搜索的索引与头部到中部的距离进行比较,如果欲搜索的索引较小,则仅需搜索链表的左半部,否则,只要从中部开始搜索右半部。
图3-1a的链表中有七个元素。该链表有一个头节点和一个尾节点。节点中的数表示该节点的索引值。如果要访问索引值为7的节点,对该链表的搜索要进行七次。在图3-1b中,增加了一个头部到中部的指针,指针上的数字表示头部到中部的距离。采用图3-1b中的办法,可以把最坏情况下的比较次数减为四次。搜索一个索引时,首先将它与头部到中间的距离进行比较,然后根据得到的结果,或者在链的左半部搜索或者在链的右半部搜索。
如果在链表的左半部分和右半部分的中间节点再增加一个指针,可以进一步减少最坏情况下的搜索比较次数。如图3-1c,在该图中有三条链。0级链就是图3-1a中的初始链,包括了所有的七个元素。1级链包括了第2、4、6个元素,而2级链只包括了第4个元素。寻找某一个索引指定的元素时,只需要在2级链上比较一次,根据比较结果,在1级链上比较一次,最后在0级链上找出所需的元素。采用图3-1c中的3级链表结构,允许在链表中进行折半查找,对所有的索引至多需要3次比较。


请问这种查找如何实现?谢谢
...全文
461 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
yeyu12521 2012-05-21
  • 打赏
  • 举报
回复
怎么做啊
gezichong 2008-08-04
  • 打赏
  • 举报
回复
LZ可以修改成C版本的。。。这个应该不难
lembo520390 2008-07-31
  • 打赏
  • 举报
回复
能否给个C语言的实现版本。万分感谢!
fallening 2008-07-31
  • 打赏
  • 举报
回复
链表?
这个不能随机访问的,在链的中部节点加一个指针,并记录头部到中部的距离,则访问的节点数可以减少到n/2+1次
有用么?
比如,第一个节点在内存的地址是0xFFFFFF00,第二个是0X00FFFFFF,第三个是0XFF00FFFF,第四个是0XFFFF00FF
你的记录头部到中部的距离记录了有什么用?
gezichong 2008-07-30
  • 打赏
  • 举报
回复
// file skip.h

#ifndef SkipList_
#define SkipList_

#include <stdlib.h>
#include <iostream.h>
#include <math.h>
#include "xcept.h"
#include "skipnode.h"

template<class E, class K>
class SkipList {
public:
SkipList(K Large, int MaxE = 10000,
float p = 0.5);
~SkipList();
bool Search(const K& k, E& e) const;
SkipList<E,K>& Insert(const E& e);
SkipList<E,K>& Delete(const K& k, E& e);
void Output();

int Level();
SkipNode<E,K> *SaveSearch(const K& k);
int MaxLevel; // max permissible chain level
int Levels; // max current nonempty chain
int CutOff; // used to decide level number
K TailKey; // a large key
SkipNode<E,K> *head; // head node pointer
SkipNode<E,K> *tail; // tail node pointer
SkipNode<E,K> **last; // array of pointers
};

template<class E, class K>
SkipList<E,K>::SkipList(K Large, int MaxE, float p)
{// Constructor.
CutOff = (int)(p * RAND_MAX);
MaxLevel =(int) ceil(log(MaxE) / log(1/p)) - 1;
TailKey = Large;
Levels = 0; // initial number of levels

// create head & tail nodes and last array
head = new SkipNode<E,K> (MaxLevel+1);
tail = new SkipNode<E,K> (0);
last = new SkipNode<E,K> *[MaxLevel+1];
tail->data = Large;

// head points to tail at all levels as empty
for (int i = 0; i <= MaxLevel; i++)
head->link[i] = tail;
}

template<class E, class K>
SkipList<E,K>::~SkipList()
{// Delete all nodes and array last.
SkipNode<E,K> *next;

// delete all nodes by deleting level 0
while (head != tail) {
next = head->link[0];
delete head;
head = next;
}
delete tail;

delete [] last;
}

template<class E, class K>
bool SkipList<E,K>::Search(const K& k, E& e) const
{// Search for element that matches k.
// Put matching element in e.
// Return false if no match.
if (k >= TailKey) return false;

// position p just before possible node with k
SkipNode<E,K> *p = head;
for (int i = Levels; i >= 0; i--) // go down levels
while (p->link[i]->data < k) // follow level i
p = p->link[i]; // pointers

// check if next node has key k
e = p->link[0]->data;
return (e == k);
}

template<class E, class K>
SkipNode<E,K> * SkipList<E,K>::SaveSearch(const K& k)
{// Search for k and save last position
// visited at each level.
// position p just before possible node with k
SkipNode<E,K> *p = head;
for (int i = Levels; i >= 0; i--) {
while (p->link[i]->data < k)
p = p->link[i];
last[i] = p; // last level i node seen
}
return (p->link[0]);
}

template<class E, class K>
int SkipList<E,K>::Level()
{// Generate a random level number <= MaxLevel.
int lev = 0;
while (rand() <= CutOff)
lev++;
//return (lev <= MaxLevel) ? lev : MaxLevel;
if (lev <= MaxLevel)
return lev;
else
return MaxLevel;
}

template<class E, class K>
SkipList<E,K>& SkipList<E,K>::Insert(const E& e)
{// Insert e if not duplicate.
K k = e; // extract key
if (k >= TailKey) throw BadInput(); // too large

// see if duplicate
SkipNode<E,K> *p = SaveSearch(k);
if (p->data == e) throw BadInput(); // duplicate

// not duplicate, determine level for new node
int lev = Level(); // level of new node
// fix lev to be <= Levels + 1
if (lev > Levels) {lev = ++Levels;
last[lev] = head;}

// get and insert new node just after p
SkipNode<E,K> *y = new SkipNode<E,K> (lev+1);
y->data = e;
for (int i = 0; i <= lev; i++) {
// insert into level i chain
y->link[i] = last[i]->link[i];
last[i]->link[i] = y;
}

return *this;
}

template<class E, class K>
SkipList<E,K>& SkipList<E,K>::Delete(const K& k, E& e)
{// Delete element that matches k. Put deleted
// element in e. Throw BadInput if no match.
if (k >= TailKey) throw BadInput(); // too large

// see if matching element present
SkipNode<E,K> *p = SaveSearch(k);
if (p->data != k) throw BadInput(); // not present

// delete node from skip list
for (int i = 0; i <= Levels &&
last[i]->link[i] == p; i++)
last[i]->link[i] = p->link[i];

// update Levels
while (Levels > 0 && head->link[Levels] == tail)
Levels--;

e = p->data;
delete p;
return *this;
}

template<class E, class K>
void SkipList<E,K>::Output()
{
/* SkipNode<E,K> *y = head->link[0];
for (; y != tail; y = y->link[0])
cout << y->data << ' ';
cout << endl;
*/
SkipNode<E,K> *y = head;
for(int i = Levels;i>=0;i--){
cout<<"Levels "<<i<<" : ";
y = head->link[i];
while(y!=tail){
cout << y->data << ' ';
y = y->link[i];
}
cout<<endl;
}
cout<<endl;
}

#endif

#ifndef SkipNode_
#define SkipNode_

template <class E, class K> class SkipList;

template<class E, class K>
class SkipNode {
friend SkipList<E,K>;
private:
SkipNode(int size)
{link = new SkipNode<E,K> *[size];}
~SkipNode() {delete [] link;}
E data;
SkipNode<E,K> **link; // 1D array of pointers
};

#endif
oo 2008-07-30
  • 打赏
  • 举报
回复
不都说的很清楚了吗?

679

社区成员

发帖
与我相关
我的任务
社区描述
智能路由器通常具有独立的操作系统,包括OpenWRT、eCos、VxWorks等,可以由用户自行安装各种应用,实现网络和设备的智能化管理。
linuxpython 技术论坛(原bbs)
社区管理员
  • 智能路由器社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧