顺序查找
一般线性表顺序查找
typedef struct{
ElemType elem[10];
int TableLen;
}SSTable;
int Search_Seq(SSTable ST,ElemType key){
ST.elem[0]=key;//哨兵引入,不用判断查找是否越界
for(int i=ST.TableLen;ST.elem[i]!=key;i--);
return i;//输出0说明没有找到
}
顺序查找平均长度 A S L 成功 = Σ i − 1 n P i ( n − i + 1 ) = n + 1 2 ASL_{成功}=\Sigma_{i-1}^nP_i(n-i+1)=\frac{n+1}{2} ASL成功=Σi−1nPi(n−i+1)=2n+1
有序表顺序查找
从前往后查,如果第i个元素小于key,第i+1个元素大于key,则查找失败直接退出。
A
S
L
不成功
=
Σ
j
=
1
n
q
j
(
l
j
−
1
)
=
1
+
2
+
⋅
⋅
⋅
+
n
+
n
n
+
1
=
n
2
+
n
n
+
1
ASL_{不成功}=\Sigma_{j=1}^nq_j(l_j-1)=\frac{1+2+···+n+n}{n+1}=\frac{n}{2}+\frac{n}{n+1}
ASL不成功=Σj=1nqj(lj−1)=n+11+2+⋅⋅⋅+n+n=2n+n+1n
二分查找
仅适用于有序顺序表
int Binary_Search(SSTable L,ElemType key){
int low=0,high=L.TableLen-1,mid;
while(low<=high){
mid=(low+high)/2;
if(L.elem[mid]==key) return mid;
if(L.elem[mid]>key) high=mid-1;
else low=mid+1;
}
return -1;
}
获得的判定树是一棵平衡二叉树
性质1
h
=
⌈
l
o
g
2
(
n
+
1
)
⌉
h=\lceil log_2(n+1)\rceil
h=⌈log2(n+1)⌉
性质2 若查找表有
n
n
n个关键字,则有
n
+
1
n+1
n+1个失败关键字
性质3 如何判断一棵树是不是折半排序的判定树:如果是下取整,每一个节点的左子树结点数都小于等于右子树;如果是上取整,每一个节点的右子树节点数都小于等于左子树
等概率情况下,查找成功平均长度
A
S
L
=
1
n
∑
i
=
1
n
l
i
=
1
n
∑
i
=
1
n
(
层数
×
每层非空结点数
)
ASL=\frac{1}{n}\sum_{i=1}^{n}l_i=\frac{1}{n}\sum_{i=1}^n(层数\times 每层非空结点数)
ASL=n1i=1∑nli=n1i=1∑n(层数×每层非空结点数)
二叉排序树
构造一棵二叉排序树的目的并不是为了排序,而是为了提高查找、插入和删除关键字的速度。
性质
1)若左子树非空,则左子树上所有结点的值均小于根节点的值
2)若右子树非空,则右子树上所有结点的值均大于根节点的值
3)左、右子树也分别是一棵二叉排序树
二叉排序树的查找
从根节点开始。
若二叉排序树非空,则将key与根节点比较,若相等则查找成功,若小于根节点关键字,在左子树查找;若大于根节点关键字,在右子树查找。
BSTNode *BST_Search(BiTree T,ElemType key){
while(T!=NULL&&key!=T.data){
if(key<T->data) T=T->lchild;
else T=T->rchild;
}
return T;
}
二叉排序树的插入
int BST_Insert(BiTree* T,ElemType k){
if((*T)==NULL){
(*T)=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->data=k;
(*T)->lchild=NULL;
(*T)->rchild=NULL;
return 1;
}
if((*T)->data==k) return 0;//该数据已经存在,无法插入
if(k<(*T)->data) return BST_Insert(&((*T)->lchild),k);
return BST_Insert(&((*T)->rchild),k);
}
二叉排序树的构造
void Creat_BST(BiTree* T,ElemType data[],int n){
(*T)=NULL;
int i=0;
while(i<n){
BST_Insert(T,data[i]);
i++;
}
}
二叉排序树的删除
1)叶结点-直接删除
2)该结点只有一棵左子树或者右子树,直接让子树替代该结点位置
3)若结点有左右两棵子树,则让z的直接后继(或直接前驱)替代z,然后删除这个直接前驱(或直接后继),这样就转化成了1)或2)
void Delete_BST(ElemType key){
BiTree* T=&first;
while((*T)!=NULL&&key!=(*T)->data){
if(key<(*T)->data) T=&((*T)->lchild);
else T=&((*T)->rchild);
}
if((*T)==NULL) return;
if((*T)->lchild==NULL&&(*T)->rchild==NULL){
(*T)=NULL;//叶子结点
return;
}
if((*T)->lchild==NULL){
(*T)=(*T)->rchild;
return;
}
if((*T)->rchild==NULL){
(*T)=(*T)->lchild;
return;
}//两种只有一个子树的情况
BiTree* s;
s=&((*T)->lchild);
while((*s)->rchild!=NULL) s=&((*s)->rchild);
(*T)->data=(*s)->data;
(*s)=NULL;
}
完整代码(已经调通)(C语言)
#include <stdio.h>
#define ElemType int
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
BiTree first;
void Creat_BST(BiTree* T,ElemType data[],int n){
(*T)=NULL;
int i=0;
while(i<n){
BST_Insert(T,data[i]);
i++;
}
}
BiTree BST_Search(BiTree T,ElemType key){
while(T!=NULL&&key!=T->data){
if(key<T->data) T=T->lchild;
else T=T->rchild;
}
return T;
}
int BST_Insert(BiTree* T,ElemType k){
if((*T)==NULL){
(*T)=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->data=k;
(*T)->lchild=NULL;
(*T)->rchild=NULL;
return 1;
}
if((*T)->data==k) return 0;//该数据已经存在,无法插入
if(k<(*T)->data) return BST_Insert(&((*T)->lchild),k);
return BST_Insert(&((*T)->rchild),k);
}
void Delete_BST(ElemType key){
BiTree* T=&first;
while((*T)!=NULL&&key!=(*T)->data){
if(key<(*T)->data) T=&((*T)->lchild);
else T=&((*T)->rchild);
}
if((*T)==NULL) return;
if((*T)->lchild==NULL&&(*T)->rchild==NULL){
(*T)=NULL;//叶子结点
return;
}
if((*T)->lchild==NULL){
(*T)=(*T)->rchild;
return;
}
if((*T)->rchild==NULL){
(*T)=(*T)->lchild;
return;
}//两种只有一个子树的情况
BiTree* s;
s=&((*T)->lchild);
while((*s)->rchild!=NULL) s=&((*s)->rchild);
(*T)->data=(*s)->data;
(*s)=NULL;
}
int data[10]={10,9,2,3,7,8};
int main(){
first=NULL;
int i=0,n=5;
Creat_BST(&first,data,5);
BiTree ans=BST_Search(first,3);
Delete_BST(2);
ans=BST_Search(first,3);
if(ans!=NULL) printf("%d",ans->data);
else printf("no");
return 0;
}