查找

1.  顺序查找:

对线性表顺序扫描进行查找,顾名思义,无需多言。其时间代价为O(n).

2. 二分查找:

要求线性表中元素是有序的。其时间代价为O(lgn).

缺点:不能用链表作存储结构,因此,当表的插入或删除操作频繁时,为维护表的有序性,需要移动表中很多记录。这种由移动记录引起的额外时间开销,就会抵消二分查找的优点。

int BinSearch(LineList R[],int n,KeyType k)
{
	int i,low=0,high=n-1,mid;   //注意这里有些是从1到n,要谨慎处理
	int find=0;                 //=0表示未找到,=1表示已找到
	while(low<=high && !find){
		mid=(low+high)/2;
		if(k < R[mid].key)
			high=mid-1;
		else if(k > R[mid].key)
			low=mid+1;
		else{
			i=mid;find=1;
		}
	}
	if(find==0)
		return -1;
	else
		return i;
}

3. 二叉查找树:

弥补二分查找关于动态查找的缺点,用二叉树作为表的组织形式。时间代价为O(lgn)它或者是一棵空树,或者是一棵具有以下特点的非空二叉树:

(1)若左子树非空,则左子树所有节点关键字均小于根结点的关键字;

(2)若右子树非空,则右子树所有节点关键字均大于(大于等于)根结点关键字;

(3)左右子树本身又各是一棵二叉查找树。

其链式存储结构节点类型为:

typedef struct tnode
{
        KeyType key;
        ElemType data;
        struct tnode *lchild,*rchild;
}BSTNode;

基本运算如下所示:

//查找
BSTNode *BSTSearch(BSTNode *bt,KeyType k)
{
	BSTNode *p=bt;
	while(p!=NULL && p->key!=k){
		if(k < p->key)
			p=p->lchild;
		else
			p=p->rchild
	}
	return p;
}
//插入
int BSTInsert(BSTNode *&bt,KeyType k)
{
	BSTNode *f,*p=bt;
	while(p!=NULL){
		if(p->key==k) return 0;
		f=p;     //f指向*p节点的双亲节点
		if(p->key > k)
			p=p->lchild;
		else
			p=p->rchild;
	}
	p=(BSTNode *)malloc(sizeof(BSTNode));
	p->key=k;
	p->lchild=p->rchild=NULL;
	if(bt==NULL)
		bt=p;
	else if(k < f->key)
		f->lchild=p;
	else 
		f->rchild=p;
	return 1;
}
//创建二叉查找树
void CreateBST(BSTNode *&bt,KeyType str[],int n)
{
	bt=NULL;
	int i=0;
	while(i<n){
		BSTInsert(bt,str[i]);
		i++;
	}
}
//删除
int BSTDelete(BSTNode *&bt,KeyType k)
{
	BSTNode *p=bt,*f,*r,*f1;
	f=NULL;                         //p指向待比较节点,f指向*p的双亲节点
	while(p!=NULL && p->key!=k){    //查找值域为k的节点
		f=p;
		if(p->key > k)
			p=p->lchild;
		else
			p=p->rchild;
	}
	if(p==NULL)    //未找到值域为k的节点
		return 0;
	else if(p->lchild==NULL){     //*p为被删节点,若他无左子树。都是用右孩子代替
		if(f==NULL)
			bt=p->rchild;
		else if(f->lchild==p){
			f->lchild=p->rchild;
			free(p);
		}
		else if(f->rchild==p){
			f->rchild=p->rchild;
			free(p);
		}
	}
	else if(p->rchild==NULL){     //*p为被删节点,若他无右子树。都是用左孩子代替
		if(f==NULL)               
			bt=p->lchild;
		else if(f->lchild==p){
			f->lchild=p->lchild;
			free(p);
		}
		else if(f->rchild==p){
			f->rchild=p->lchild;
			free(p);
		}
	}
	else{                          //*p为被删节点,若他有左子树和右子树
		f1=p;r=p->lchild;           //查找*p的左子树中的最右下节点*r.它一定是无右子树的节点,*f1作为r的双亲
		while(r->rchild!=NULL){
			f1=r;
			r=r->rchild;
		}
		if(f1->lchild==r)         //无论是左孩子还是右孩子,都删除*r,用它代替*p
			f1->lchild=r->rchild;
		else if(f1->rchild==r)
			f1->rchild=r->lchild;
		r->lchild=p->lchild;
		r->rchild=p->rchild;
		if(f==NULL)
			bt=r;
		else if(f->lchild==p)
			f->lchild=r;
		else
			f->rchild=r;
		free(p);
	}
	return 1;
}

还是那句话,画个图就清晰了。
4. 红黑树(二叉平衡树):待续

5. hash查找:

最关键的就是找到一个好的hash函数,然后有好的解决冲突的方法。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值