一、要求:
(1)随机产生n个互不相同的两位整数,构造一个查找表。
(2)输入一个整数,利用顺序查找法在查找表中查找该整数是否存在。若查找成功,返回该整数在表中的位置;查找失败则返回0。
(3)对查找表按递增顺序进行排序。
(4)输入一个整数,利用折半查找法在有序表中查找该整数是否存在。若查找成功,返回该整数在表中的位置;查找失败则返回0。
(5)输入互不相同的一组整数,构造一棵二叉排序树,要求:
① 按递减有序的顺序输出;
② 输入一个整数,查找该整数是否在该二叉排序树中,查找成功返回1,否则返回0;
③ 在②中,若查找成功,则将该结点从二叉排序树中删除。
二、思路:
①随机产生10~20个不同的两位整数,可利用srand(time(NULL))产生随机数。
②利用顺序查找法查找时,从查找表的后面向前查找,若得到的最后的关键字值等于key的记录的位置为0,说明查找失败,否则查找成功。
③对查找表排序可利用冒泡排序法。
④折半查找:在有序表中,首先选取表中间记录的关键字与给定值进行比较。若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半子表中继续查找;若给定值大于中间记录的关键字,则在中间记录的右半子表中继续查找。重复上述过程,直至查找成功;或当前的查找区间无记录,则查找失败。
⑤若按递减有序的顺序输出二叉排序树,则需建立逆二叉排序树;
⑥建立二叉排序树的过程就是从空树开始,不断向二叉排序树中插入结点的过程。
⑦二叉排序树的查找,若二叉排序树为空,则查找失败。若非空,则将给定值与根结点的关键字进行比较:
若给定值与根结点的关键字相同,则查找成功。
若给定值小于根结点的关键字,则在根结点的左子树上查找。
若给定值大于根结点的关键字,则在根结点的右子树上查找。
⑧二叉树的插入:
若在二叉排序树中查找失败,则为关键字key申请新结点,并将该结点插到插到二叉排序树中合适的位置处。
若二叉排序树为空,则为待插入关键字key申请结点,并作为根结点插入。
若二叉排序树非空,则将关键字key与根结点的关键字的值进行比较:
若key=bst->data.key,查找成功,无需插入;
若keydata.key,沿左子树查找,若查找失败,将新结点插到合适的位置处。
若key>bst->data.key,沿右子树查找,若查找失败,将新结点插到合适的位置处。
三、代码:
(1),(2),(3),(4):
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MAX 100 //查找表大小
typedef struct{ //查找表的数据元素的类型定义
int key; //关键字的类型
}Elemtype;
typedef struct{ //查找表的类型定义
Elemtype elem[MAX+1];
int length;
}SSTable;
void Create(SSTable &ST){ //建立查找表
int i,j,k,m;
srand(time(NULL));
m = rand();
while(m<10 || m>20)
m = rand()%20; //随机产生10--20个两位整数
printf("随机产生%d个两位整数:",m);
ST.length = m+1;
srand(time(NULL));
for(i=1;i<=m;i++){
k = rand()%90+10;
j=1;
while(j<i && k!=ST.elem[j].key){j++;} //检验新生成的随机数是否与前面生成的随机数相同
if(j<i)
{ i--; continue;} //若相同,则重新生成k
else
ST.elem[i].key = k;
}//for
}
void PrintST(SSTable ST){
//输出查找表
int i;
for(i=1;i<ST.length;i++)
printf("%3d",ST.elem[i].key);
printf("\n");
}
int Search_Seq(SSTable ST,int key){
//在查找表ST中查找关键字为key的记录
int i;
ST.elem[0].key = key;
i = ST.length;
while(ST.elem[i].key != key)
i--;
return i;
}
void Sort_ST(SSTable &ST){
//对查找表按递增顺序进行排序
int i,j,t;
for(i=1;i<ST.length;i++)
for(j=1;j<ST.length-i;j++)
if(ST.elem[j].key>ST.elem[j+1].key){
t = ST.elem[j].key;
ST.elem[j].key = ST.elem[j+1].key;
ST.elem[j+1].key = t;
}//if
}
int Search_Bin(SSTable ST,int key){
//在有序表ST中折半查找关键字为key的元素
int low,high,mid;
low = 1; high = ST.length;
while(low<=high){
mid = (low+high)/2;
if(key == ST.elem[mid].key)
return mid;
else if(key<ST.elem[mid].key)
high = mid-1;
else
low = mid +1;
}//while
return 0;
}
void main(){
int f1,f2,L1,L2;
SSTable ST;
Create(ST);
PrintST(ST);
printf("请输入要用顺序查找法查找的元素:");
scanf("%d",&f1);
L1 = Search_Seq(ST,f1); //顺序查找法
if(L1 == 0)
printf("%d不存在!\n",f1);
else
printf("%d的位置为%d\n",f1,L1);
Sort_ST(ST); //排序
printf("排序后查找表为:");
PrintST(ST);
printf("请输入要用折半查找法查找的元素:");
scanf("%d",&f2);
L2 = Search_Bin(ST,f2); //折半查找法
if(L2 == 0)
printf("%d不存在!\n",L2);
else
printf("%d的位置为%d\n",f2,L2);
}
结果:
(5)二叉排序树:
#include<stdio.h>
#include<stdlib.h>
typedef struct{ //查找表的数据元素的类型定义
int key; //关键字的类型
}Elemtype;
typedef struct BiTNode{ //二叉树
Elemtype data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//typedef BiTree BT;
int SearchBST(BiTree bst,int key,BiTree &p){
//在二叉排序树bst中查找关键字等于key的数据元素,若查找成功,p指向查找成功的结点,否则p指向查找过程中最后访问的结点
BiTree s,f;
s=bst; f=NULL;
if(!s) {p = f; return 0;} //空树,查找失败
while(s!=NULL)
if(key == s->data.key){ //查找成功
p=s; return 1;}
else if(key > s->data.key){
f=s;s=s->lchild;} //进入左子树
else{
f=s;s=s->rchild;} //右子树
p=f; return 0;
}
void InsertBST(BiTree &bst,Elemtype e){
//在二叉排序树中插入元素e
BiTree s,p;
if(bst == NULL){ //空树,新结点作为根
bst = (BiTree)malloc(sizeof(BiTNode));
bst->data = e;
bst->lchild = bst->rchild = NULL;
}
else{
if(!SearchBST(bst,e.key,p)){ //未查到
s = (BiTree)malloc(sizeof(BiTNode));
s->data = e;
s->lchild = s->rchild = NULL;
if(e.key>p->data.key)
p->lchild = s;
else
p->rchild = s;
}//if
}//else
}
void InOrderTraverse(BiTree bst){
if(bst){ //中序遍历二叉排序树
InOrderTraverse(bst->lchild);
printf("%3d",bst->data);
InOrderTraverse(bst->rchild);
}
}
void CreateBST(BiTree &bst){
//根据输入的整数,建立一棵 逆二叉排序树
Elemtype x; BiTree p;
bst = NULL;
printf("请输入一组互不相同的整数:");
scanf("%d",&x.key);
while(x.key!=0){ //输入0表示结束
if(!SearchBST(bst,x.key,p))
InsertBST(bst,x);
scanf("%d",&x.key);
}
}
void DeleteNode(BiTree &bst,int key){
//在二叉排序树bst中删除值为key的结点,是bst仍保持其有序性
BiTree p,f,q,s,pc;
p = bst; f=NULL; //f为双亲结点
while(p && p->data.key!=key){ //在bst中查找被删结点
f=p;
if(p->data.key < key)
p = p->lchild;
else
p = p->rchild;
}//while
if(!p){
printf("该树中没有所需删除的结点\n");
return ;
}//if
if(p->lchild && p->rchild){
q=p; s=p->rchild;
while(s->lchild){
q=s; s=s->lchild;
}//while
p->data = s->data;
if(q==p) q->rchild = s->rchild;
else q->lchild = s->rchild;
free(s);
}//if
else{
if(p->lchild) pc = p->lchild; //被删结点只有左子树
else pc = p->rchild; //只有右子树
if(!f) bst = pc; //被删结点为根结点
else if(f->lchild = p) //被删结点是其双亲的左孩子
f->lchild = pc;
else f->rchild = pc; //右孩子或叶子
free(p);
}//else
}
void main(){
int f,L;
BiTree bst,p;
CreateBST(bst);
printf("逆序输出二叉排序树:");
InOrderTraverse(bst);
printf("\n");
printf("请输入要查找的整数:");
scanf("%d",&f);
L= SearchBST(bst,f,p);
if(L==1){
printf("查找成功!\n");
DeleteNode(bst,f);
printf("删除后逆序输出二叉排序树:");
InOrderTraverse(bst);
printf("\n");
}
else
printf("该数不在二叉排序树中!\n");
}
结果:
Directions:
仅代表初识数据结构时思路。