算法8.1设置监视哨的顺序查找法
int SeqSearch(RecordList l, KeyType k)
/*在顺序表l中顺序查找其关键字等于k的元素,若找到,则函数值为该元素在表中的位置,否则为0*/
{
int i;
l.r[0].key=k;
i=l.length;
while (l.r[i].key!=k) i--;
return(i);
}
算法8.2不设置监视当的顺序查找法
int SeqSearch(RecordList l, KeyType k)
/*不用"监视哨"法,在顺序表中查找关键字等于k的元素*/
{
int i;
i=l.length;
while (i>=1&&l.r[i].key!=k) i--;
if (i>=1)
return(i);
else
return (0);
}
算法8.3折半查找法
int BinSrch(RecordList l, KeyType k)
/*在有序表l中折半查找其关键字等于k的元素,若找到,则函数值为该元素在表中的
位置*/
{
int low,high,mid;
low=1;
high=l.length;/*置区间初值*/
while( low <= high)
{
mid=(low+high) / 2;
if (k==l.r[mid]. key)
return (mid);/*找到待查元素*/
else
if (k<l.r[mid]. key)
high=mid-1;/*未找到,则继续在前半区间进行查找*/
else
low=mid+1;/*继续在后半区间进行查找*/
}
return (0);
}
算法8.4二叉排序树查找的递归算法
BSTree SearchBST(BSTree bst, KeyType key)
/ *在根指针bst所指二叉排序树中,递归查找某关键字等于key的元素,若查找成功,返回指向该元素结点指针,否则返回空指针* /
{
if (!bst)
return NULL;
else
if (bst->key == key)
return bst;/ *查找成功* /
else
if (bst->key > key)
return SearchBST(bst->lchild, key);/ *在左子树继续查找* /
else
return SearchBST(bst->rchild, key);/ *在右子树继续查找* /
}
算法8.5二叉排序树查找的非递归算法
BSTree SearchBST(BSTree bst, KeyType key)
/*在根指针bst所指二叉排序树bst上,查找关键字等于key的结点,若查找成功,返回指向该元素结点指针,否则返回空指针*/
{
BSTree q;
q=bst;
while(q)
{
if (q->key == key)
return q; /*查找成功*/
if (q->key > key)
q=q->lchild; /*在左子树中查找*/
else
q=q->rchild; /*在右子树中查找*/
}
return NULL; /*查找失败*/
}/*SearchBST*/
算法8.6二叉排序树插入的递归算法
void InsertBST(BSTree *bst, KeyType key)
/*若在二叉排序树中不存在关键字等于key的元素,插入该元素*/
{
BSTree s;
if (*bst == NULL)/*递归结束条件*/
{
s=(BSTree)malloc(sizeof(BSTNode));/*申请新的结点s*/
s-> key=key;
s->lchild=NULL;
s->rchild=NULL;
*bst=s;
}
else
if (key < (*bst)->key)
InsertBST(&((*bst)->lchild), key);/*将s插入左子树*/
else
if (key > (*bst)->key)
InsertBST(&((*bst)->rchild), key); /*将s插入右子树*/
}
算法8.7二叉排序树插入的非递归算法
int InsertBST(BSTree *bst, KeyType K)
/*若在二叉排序树中不存在关键字等于key的元素,插入该元素*/
{
BSTree f, q, s;
s=(BSTree)malloc(sizeof(BSTNode));
s->key = K;
s->lchild = NULL;
s->rchild = NULL;
if ( *bst == NULL )
{
*bst = s;
return 1;
}
f = NULL;
q = *bst;
while( q )
{
if ( q->key == K )
return 0;
if( K < q->key )
{
f = q;
q = q->lchild;
}
else
{
f = q;
q = q->rchild;
}
}
if ( K < f->key )
f->lchild = s;
else
f->rchild = s;
return 1;
}
算法8.8创建二叉排序树
void CreateBST(BSTree *bst)
/*从键盘输入元素的值,创建相应的二叉排序树*/
{
KeyType key;
*bst=NULL;
scanf("%d", &key);
while (key!=ENDKEY) /*ENDKEY为自定义常量*/
{
InsertBST(bst, key);
scanf("%d", &key);
}
}
算法8.9在二叉排序树中删除结点
BSTNode * DelBST(BSTree t, KeyType k) /*在二叉排序树t中删去关键字为k的结点*/
{
BSTNode *p, *f,*s ,*q;
p=t;
f=NULL;
while(p) /*查找关键字为k的待删结点p*/
{
if(p->key==k ) break; /*找到则跳出循环*/
f=p; /*f指向p结点的双亲结点*/
if(p->key>k)
p=p->lchild;
else
p=p->rchild;
}
if(p==NULL) return t; /*若找不到,返回原来的二叉排序树*/
if(p->lchild==NULL) /*p无左子树*/
{
if(f==NULL)
t=p->rchild; /*p是原二叉排序树的根*/
else
if(f->lchild==p) /*p是f的左孩子*/
f->lchild=p->rchild ; /*将p的右子树链到f的左链上*/
else /*p是f的右孩子*/
f->rchild=p->rchild ; /*将p的右子树链到f的右链上*/
free(p); /*释放被删除的结点p*/
}
else /*p有左子树*/
{
q=p;
s=p->lchild;
while(s->rchild) /*在p的左子树中查找最右下结点*/
{
q=s;
s=s->rchild;
}
if(q==p)
q->lchild=s->lchild ; /*将s的左子树链到q上*/
else
q->rchild=s->lchild;
p->key=s->key; /*将s的值赋给p*/
free(s);
}
return t;
} /*DelBST*/
算法8.10平衡二叉排序树的插入操作
void ins_AVLtree(AVLTree *avlt , KeyType K)
/*在平衡二叉树中插入元素k,使之成为一棵新的平衡二叉排序树*/
{
AVLTNode *S;
AVLTNode *A,*FA,*p,*fp,*B,*C;
S=(AVLTree)malloc(sizeof(AVLTNode));
S->key=K;
S->lchild=S->rchild=NULL;
S->bf=0;
if (*avlt==NULL)
*avlt=S;
else
{
/* 首先查找S的插入位置fp,同时记录距S的插入位置最近且
平衡因子不等于0(等于-1或1)的结点A,A为可能的失衡结点*/
A=*avlt; FA=NULL;
p=*avlt; fp=NULL;
while (p!=NULL)
{
if (p->bf!=0)
{
A=p; FA =fp;
}
fp=p;
if (K < p->key)
p=p->lchild;
else
p=p->rchild;
}
/* 插入S*/
if (K < fp->key)
fp->lchild=S;
else
fp->rchild=S;
/* 确定结点B,并修改A的平衡因子 */
if (K < A->key)
{
B=A->lchild;
A->bf=A->bf+1;
}
else
{
B=A->rchild;
A->bf=A->bf-1;
}
/* 修改B到S路径上各结点的平衡因子(原值均为0)*/
p=B;
while (p!=S)
{
if (K < p->key)
{
p->bf=1;
p=p->lchild;
}
else
{
p->bf=-1;
p=p->rchild;
}
/* 判断失衡类型并做相应处理 */
if (A->bf==2 && B->bf==1) /* LL型 */
{
B=A->lchild;
A->lchild=B->rchild;
B->rchild=A;
A->bf=0;
B->bf=0;
if (FA==NULL)
*avlt=B;
else
if (A==FA->lchild)
FA->lchild=B;
else
FA->rchild=B;
}
else
if (A->bf==2 && B->bf==-1) /* LR型 */
{
B=A->lchild;
C=B->rchild;
B->rchild=C->lchild;
A->lchild=C->rchild;
C->lchild=B;
C->rchild=A;
if (S->key < C->key)
{
A->bf=-1;
B->bf=0;
C->bf=0;
}
else
if (S->key >C->key)
{
A->bf=0;
B->bf=1;
C->bf=0;
}
else
{
A->bf=0;
B->bf=0;
}
if (FA==NULL)
*avlt=C;
else
if (A==FA->lchild)
FA->lchild=C;
else
FA->rchild=C;
}
else
if (A->bf==-2 && B->bf==1) /* RL型 */
{
B=A->rchild;
C=B->lchild;
B->lchild=C->rchild;
A->rchild=C->lchild;
C->lchild=A;
C->rchild=B;
if (S->key <C->key)
{
A->bf=0;
B->bf=-1;
C->bf=0;
}
else
if (S->key >C->key)
{
A->bf=1;
B->bf=0;
C->bf=0;
}
else
{
A->bf=0;
B->bf=0;
}
if (FA==NULL)
*avlt=C;
else
if (A==FA->lchild)
FA->lchild=C;
else
FA->rchild=C;
}
else
if (A->bf==-2 && B->bf==-1) /* RR型 */
{
B=A->rchild;
A->rchild=B->lchild;
B->lchild=A;
A->bf=0;
B->bf=0;
if (FA==NULL)
*avlt=B;
else
if (A==FA->lchild)
FA->lchild=B;
else
FA->rchild=B;
}
}
}
}
算法8.11在B树中查找关健字为k的元素
Boolean srch_mbtree (Mbtree mbt, KeyType k, Mbtree *np, int *pos)
/*在根为mbt的B_树中查找关键字k,如果查找成功,则将所在结点地址放入np,将结点内位置序号放入pos,并返回true;否则,将k应被插入的结点地址放入np,将结点内应插位置序号放入pos,并返回false*/
{
Mbtree p,fp;
Boolean found;
int i;
p = mbt;
fp = NULL;
found = false;
i = 0;
while (p != NULL && !found)
{
i = search (p, k);
if (i>0 && p->key[i] == k)
found = true;
else
{
fp = p;
p = p->ptr[i];
}
}
if (found)
{
*np = p;
*pos = i;
return true;
}
else
{
*np = fp;
*pos = i;
return false;
}
}
算法8.12在B树中寻找小于等于关键字k的关键字序号
int search (Mbtree mbt, KeyType key )
/*在mbt指向的结点中,寻找小于等于key的最大关键字序号*/
{
int n,i;
n = mbt->keynum ;
i = 1 ;
while (i <= n && mbt->key[i] <= key ) i ++;
return (i - 1); /* 返回小于等于key的最大关键字序号 ,为0 时表示应到
最左分支找,越界时表示应到最右分支找 */
}
算法8.13B树的插入算法
void ins_mbtree(Mbtree *mbt, KeyType k, Mbtree q, int i)
/* 在m阶B_树t中插入k:如果mbt=NULL,则生成初始根(此时q=NULL,i=0);否则q指向某个最下层非终端结点,k应插在该结点中q->key[i+1]处,插入后如果q->keynum>m-1,则进行分裂处理*/
{
Mbtree q1,ap;
Mbtree new_root;
int s;
int finished;
int x;
if (*mbt==NULL)
{
*mbt =(Mbtree)malloc(sizeof(Mbtnode));
(*mbt)->keynum=1;
(*mbt)->parent=NULL;
(*mbt)->key[1]=k;
(*mbt)->ptr[0]=NULL;
(*mbt)->ptr[1]=NULL;
}
else
{
x=k; /* 将x插到q->key[i+1] 处 */
ap=NULL; /* 将ap插到q->ptr[i+1] 处 */
finished=NULL;
while (q!=NULL && !finished) /* q=NULL 表示已经分裂到根 */
{
insert(q, i, x, ap);
if (q->keynum<m)
finished=TRUE; /* 不再分裂 */
else
{
s=ceil((float)m/2); /* s= */
split(q, &q1); /* 分裂 */
x=q->key[s];
ap=q1;
q=q->parent;
if (q!=NULL)
i=search(q,x); /* search( ) 的定义参见B_树查找一节 */
}
}
if (!finished) /* 表示根结点要分裂,并产生新根 */
{
new_root=(Mbtree)malloc(sizeof(Mbtnode));
new_root->keynum=1;
new_root->parent=NULL;
new_root->key[1]=x;
new_root->ptr[0]=*mbt;
new_root->ptr[1]=ap;
*mbt=new_root;
}
}
}
算法8.14在B_树的指定位置插上key
void insert(Mbtree mbp, int ipos, KeyType key, Mbtree rp)
/* 在mbp->key[ipos +1]处插上key, 在mbp->ptr[ipos+1]处插上rp */
{
int j;
for (j=mbp->keynum; j>= ipos +1 ; j--)
{
mbp->key[j+1]=mbp->key[j];
mbp->ptr[j+1]=mbp->ptr[j];
}
mbp->key[ipos+1]=key;
mbp->ptr[ipos+1]=rp;
mbp->keynum++;
}
算法8.15B_树的分裂算法
void split (Mbtree oldp, Mbtree *newp)
{/* B_树的分裂过程 */
int s,n,i;
s=ceil((float)m/2); /* s= */
n=m-s;
*newp=(Mbtree)malloc(sizeof(Mbtnode));
(*newp)->keynum=n;
(*newp)->parent=oldp->parent;
(*newp)->ptr[0]=oldp->ptr[s];
for (i=1 ; i<=n ; i++)
{ (*newp)->key[i]=oldp->key[s+i];
(*newp)->ptr[i]=oldp->ptr[s+i];
}
oldp->keynum=s-1;
}
算法8.16哈希表的查找算法
int HashSearch( HashTable ht, KeyType K)
{
int h0;
int i;
int hi;
h0=hash(K);
if (ht[h0].key==NULLKEY)
return (-1);
else
if (ht[h0].key==K)
return (h0);
else /* 用线性探测再散列解决冲突 */
{
for (i=1; i<=m-1; i++)
{
hi=(h0+i) % m;
if (ht[hi].key==NULLKEY)
return (-1);
else
if (ht[hi].key==K)
return (hi);
}
return (-1);
}
}
典型题例3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define m 30
#define NULLKEY NULL
typedef struct
{
char *key;
}RecordType;
typedef RecordType HashTable[m];
int hash(char *k)
{
int h;
char k0;
k0 = k[0];
switch(k0)
{
case 'a':
h=1;
break;
case 'b':
h=2;
break;
case 'c':
h=3;
break;
case 'd':
h=4;
break;
case 'e':
h=5;
break;
case 'f':
h=6;
break;
case 'g':
h=7;
break;
case 'h':
h=8;
break;
case 'i':
h=9;
break;
case 'j':
h=10;
break;
case 'k':
h=11;
break;
case 'l':
h=12;
break;
case 'm':
h=13;
break;
case 'n':
h=14;
break;
case 'o':
h=15;
break;
case 'p':
h=16;
break;
case 'q':
h=17;
break;
case 'r':
h=18;
break;
case 's':
h=19;
break;
case 't':
h=20;
break;
case 'u':
h=21;
break;
case 'v':
h=22;
break;
case 'w':
h=23;
break;
case 'x':
h=24;
break;
case 'y':
h=25;
break;
case 'z':
h=26;
break;
default:
break;
}
return h;
}
void createhash(HashTable *ht)
{
int i,j;
int n;
char p[10];
int hj;
for(i=0; i<m; i++)
(*ht)[i].key = NULLKEY;
printf("请输入哈希表的元素个数:");
scanf("%d",&n);
for(i=1; i<=n; i++)
{
printf("请输入第%d个元素:",i);
fflush(stdin);
gets(p);
j = hash(p);
// printf("ok%d\n",j);
if ((*ht)[j].key == NULLKEY)
{
(*ht)[j].key=(char*)malloc(10*sizeof(char));
strcpy((*ht)[j].key,p);
// printf("ok\n");
}
else
{
for (i=1; i<=m-1; i++)
{
hj=(j+i) % m;
if ((*ht)[hj].key==NULLKEY)
{
(*ht)[hj].key=(char*)malloc(10*sizeof(char));
strcpy((*ht)[hj].key,p);
i = m;
}
}
}
}
}
int HashSearch( HashTable ht, char *K)
{
int h0;
int i;
int hi;
int result;
h0=hash(K);
if (ht[h0].key==NULLKEY)
return (-1);
else
{
result = strcmp(ht[h0].key,K);
if (result == 0)
return (h0);
else /* 用线性探测再散列解决冲突 */
{
for (i=1; i<=m-1; i++)
{
hi=(h0+i) % m;
if (ht[hi].key==NULLKEY)
return (-1);
else
{
result = strcmp(ht[hi].key,K);
if (result == 0)
return (hi);
}
}
return (-1);
}
}
}
void printword(HashTable ht)
/*按第一个字母的顺序输出ht哈希表中的标识符,处理冲突的方法为线性探测开放定址法*/
{
int i,j;
for(i=1; i<=26; i++)
{
j = i;
while(ht[j].key != NULLKEY)
{
if(hash(ht[j].key) == i)
printf("%s\n",ht[j].key);
j = (j+1)%m;
}
}
}
float unsucclength(HashTable ht)
/*模拟手工计算等概率查找情况下查找不成功的平均查找长度算法 */
{
int i,j;
int count;
int asl = 0;
float unasl;
for(i=1; i<=26; i++)
{
j = i;
count = 1;
while(ht[j].key != NULLKEY)
{
count++;
j=(j+1)%m;
}
asl = asl + count;
}
unasl = (float)asl/26;
return (unasl);
}
void main()
{
// int i,j;
char *k;
int result;
HashTable ht;
float uasLength;
createhash(&ht);
k = (char *)malloc(10*sizeof(char));
printf("请输入要查找的元素:");
fflush(stdin);
gets(k);
result = HashSearch(ht,k);
if(result == -1)
printf("未找到!\n");
else
printf("元素位置为%d\n",result);
printword(ht);
uasLength = unsucclength(ht);
printf("不成功的平均查找长度为%f\n",uasLength);
}
其它
int InsertBST(BSTree *bst, KeyType K)
/*若在二叉排序树中不存在关键字等于key的元素,插入该元素*/
{
BSTree f, q, s;
s=(BSTree)malloc(sizeof(BSTNode));
s->key = K;
s->lchild = NULL;
s->rchild = NULL;
if ( *bst == NULL )
{
*bst = s;
return 1;
}
f = NULL;
q = *bst;
while( q )
{
if ( q->key == K )
return 0;
if( K < q->key )
{
f = q;
q = q->lchild;
}
else
{
f = q;
q = q->rchild;
}
}
if ( K < f->key )
f->lchild = s;
else
f->rchild = s;
return 1;
}
8.1-8.3顺序结构头文件
#include <stdio.h>
#include <stdlib.h>
#define LIST_SIZE 20
typedef char KeyType;
typedef int OtherType;
typedef struct
{
KeyType key;
OtherType other_data;
}RecordType;
typedef struct
{
RecordType r[LIST_SIZE+1]; /* r[0]为工作单元 */
int length;
}RecordList;
8.4-8.9二叉排序树头文件
#include <stdio.h>
#include <stdlib.h>
#define ENDKEY 0
typedef int KeyType;
typedef struct node
{
KeyType key ; /*关键字的值*/
struct node *lchild,*rchild;/*左右指针*/
}BSTNode, *BSTree;
8.10平衡二叉排序树头文件
#include <stdio.h>
#include <stdlib.h>
#define ENDKEY 0
typedef int KeyType;
typedef struct node
{
KeyType key ; /*关键字的值*/
int bf;
struct node *lchild,*rchild;/*左右指针*/
}AVLTNode, *AVLTree;
8.11-8.15B树头文件
#include <stdio.h>
#include <stdlib.h>
#define m 3
#define NULL 0
#define TRUE 1
typedef int Boolean;
typedef int KeyType;
typedef struct Mbtnode
{
struct Mbtnode *parent;
int keynum;
KeyType key[m+1];
struct Mbtnode *ptr[m+1];
} Mbtnode, *Mbtree;
8.16-8.17哈希表头文件
#include <stdio.h>
#include <stdlib.h>
#define m 13
#define NULLKEY 0
typedef int KeyType; /* 假设关键字为整型 */
typedef struct
{
KeyType key;
}RecordType;
typedef RecordType HashTable[m];