数据结构实验五.docx
《数据结构实验五.docx》由会员分享,可在线阅读,更多相关《数据结构实验五.docx(34页珍藏版)》请在冰豆网上搜索。
数据结构实验五
实验五查找与排序
实验课程名:
数据结构(c语言版)
专业班级:
学号:
姓名:
实验时间:
实验地点:
指导教师:
一、实验目的
1、进一步掌握指针变量、动态变量的含义。
2、掌握二叉树的结构特性,以及各种存储结构的特点和适用范围。
3、掌握用指针类型描述、访问和处理二叉树的运算
二、实验的内容和步骤
下面是查找与排序的部分基本操作实现的算法,请同学们自己设计主函数和部分算法,调用这些算法,完成下面的实验任务。
#defineMAX_LENGTH100
typedefintKeyType;
/*顺序查找表的存储类型*/
typedefstruct//definestructureSSTable
{KeyType*elem;
intlength;
}SSTable;
/*在查找表中顺序查找其关键字等于key的数据元素。
*/
intSearch_Seq(SSTableST,KeyTypekey)//Search_Seqfunction
{inti;
ST.elem[0]=key;
for(i=ST.length;!
(ST.elem[i]==key);--i)
;
return(i);//ifnotfind,returni=0
}
/*在有序查找表中折半查找其关键字等于key的数据元素*/
intSearch_Seq(SSTableST,KeyTypekey)//Search_Seqfunction
{intmid,low=1,high=ST.length;
while(low<=high)
{mid=(low+high)/2;
if(key==ST.elem[mid])
return(mid);
elseif(keyhigh=mid-1;
else
low=mid+1;
}
return(0);
}
/*在二叉排序树中查找某关键字等于key的数据元素*/
intSearchBST(BiTreeT,KeyTypekey,BiTreef,BiTree&p)//SearchBST()Sub-function
{if(!
T)
{p=f;
return(ERROR);
}
elseif(key==T->data)
{p=T;
return(OK);
}
elseif(keydata)
SearchBST(T->lchild,key,T,p);
else
SearchBST(T->rchild,key,T,p);
}
/*二叉排序树中插入算法*/
intSearchBST(BiTreeT,KeyTypekey,BiTreef,BiTree&p)//SearchBST()
{if(!
T)
{p=f;
return(ERROR);
}
elseif(key==T->data)
{p=T;
return(OK);
}
elseif(keydata)
SearchBST(T->lchild,key,T,p);
else
SearchBST(T->rchild,key,T,p);
}//SearchBST()end
/*二叉排序树中删除算法*/
intDelete(BiTree&p)//Delete()sub-function
{BiTreeq,s;
if(!
p->data)
{q=p;
p=p->lchild;
free(q);
}
elseif(!
p->lchild)
{q=p;
p=p->rchild;
free(q);
}
else
{q=p;
s=p->lchild;
while(s->rchild)
{q=s;
s=s->rchild;
}
p->data=s->data;
if(q!
=p)q->rchild=s->lchild;
elseq->lchild=s->rchild;
}
}
/*链地址Hash表类型*/
typedefintElemType;
typedefstructLNode
{ElemTypekey;
structLNode*next;
}LNode,*LinkList;
typedef LNode*CHashTable[MAXSIZE] ; //链地址Hash表类型
/*求Hash函数*/
intH(ints)//
{
if(s)
returns%11;//求关键字
else
return0;
}//H
/*输入数据的关键字函数*/
ElemTypeInputkey()
{
ElemTypex;
cout<<"请输入数据"<cin>>x;
returnx;
}
/*输入一组关键字,建立Hash表,表长为m,用链地址法处理冲突*/
intBuild_Hash(CHashTable&T,intm)
{ElemTypekey;
LNode*q;
intn;
if(m<1)returnERROR;
for(inti=0;iT[i]=NULL;//哈希表初始化
while((key=Inputkey())!
=0)//输入元素有效
{q=(LNode*)malloc(sizeof(LNode));
q->data=key;
q->next=NULL;
n=H(key);//查HASH表得到指针数组的地址
q->next=T[n];//原来的头指针后移
T[n]=q;//新元素插入头部
}//while
returnOK;
}
/*输出用链地址法处理冲突的Hash表*/
intPrint_Hash(CHashTable&T)
{
LNode*q;
intn;
for(inti=0;i<11;i++)
{
q=T[i];//哈希表初始化
while(q)//输入元素有效
{
cout<data<<"";
q=q->next;
}
cout<}
returnOK;
}
/*定义每个记录(数据元素)的结构*/
Typedefstruct{//定义每个记录(数据元素)的结构
KeyTypekey;//关键字
InfoTypeotherinfo;//其它数据项
}RecordType,node;//例如node.key表示其中一个分量
/*定义顺序表L的结构*/
Typedefstruct{//定义顺序表L的结构
RecordTyper[MAXSIZE+1];//存储顺序表的向量
//r[0]一般作哨兵或缓冲区
intlength;//顺序表的长度
}SqList,L;//例如L.r或L.length表示其中一个分量
//若r数组是表L中的一个分量且为node类型,则r中某元素的key分量表示为:
r[i].key
/*直接插入排序算法的实现:
*/
voidInsertSort(SqList&L){//对顺序表L作直接插入排序
for(i=2;i<=L.length;++i)//直接在原始无序表L中排序
if(L.r[i].key{L.r[0]=L.r[i];//先将待插入的元素放入“哨兵”位置
L.r[i]=L.r[i-1];//子表元素开始后移
for(j=i-2;L.r[0].key//只要子表元素比哨兵大就不断后移
L.r[j+1]=L.r[0];//直到子表元素小于哨兵,将哨兵值送入
//当前要插入的位置(包括插入到表首)
}//if
}//InsertSort
/*希尔排序算法(主程序)*/
voidShellSort(SqList&L,intdlta[],intt)
{//按增量序列dlta[0…t-1]对顺序表L作Shell排序
for(k=0;k{
ShellInsert(L,dlta[k]);
}
}//ShellSort
/*希尔排序算法(其中某一趟的排序操作)*/
voidShellInsert(SqList&L,intdk)
{//对顺序表L进行一趟增量为dk的Shell排序,dk为步长因子
for(i=dk+1;i<=L.length;++i)
if(r[i].key{r[0]=r[i];
for(j=i-dk;j>0&&(r[0].keyr[j+dk]=r[j];
r[j+dk]=r[0];
}//if
}//ShellInsert
//理解难点:
不提前处理i子集后部元素,每次只考虑子集的前部(j=j-dk),
//第二轮也只考虑i+1那个子集的前部。
/*一趟快速排序算法(针对一个子表的操作)*/
intPartition(SqList&L,intlow,inthigh){//一趟快排
//交换子表r[low…high]的记录,使支点(枢轴)记录到位,并返回其位置。
返回时,在支点之前的记录均不大于它,支点之后的记录均不小于它。
r[0]=r[low];//以子表的首记录作为支点记录,放入r[0]单元
(续下页)
pivotkey=r[low].key;//取支点的关键码存入pivotkey变量
while(low=pivotkey)--high;
r[low]=r[high];//比支点小的记录交换到低端;
while(lowr[high]=r[low];//比支点大的记录交换到高端;
}
r[low]=r[0];//支点记录到位;
returnlow;//返回支点记录所在位置。
}//Partition
/*整个快速排序的递归算法:
*/
voidQSort(SqList&L,intlow,inthigh)
{//对顺序表L中的子序列r[low…high]作快速排序
if(low{pivot=Partition(L,low,high);
QSort(L,low,pivot-1);
QSort(L,pivot+1,high);
}//if
}//QSort
/*简单选择排序的算法*/
VoidSelectSort(SqList&L){
for(i=1;ij=SelectMinKey(L,i);
if(i!
=j)r[i]↔r[j];
}//for
}//SelectSort
/*建堆算法(即堆排序算法中的第一步)*/
voidHeapSort(HeapType&H){
//H是顺序表,含有H.r[]和H.length两个分量
for(i=length/2;i>0;--i)//把r[1…length]建成大根堆
HeapAdjust(r,i,length);//使r[i…length]成为大根堆
……
}//HeapSort
/*堆排序的算法实现*/
voidHeapSort(HeapType&H)
{
//对顺序表H进行堆排序
for(i=H.length/2;i>0;--i)
HeapAdjust(H,i,H.length);//for,建立初始堆
for(i=H.length;i>1;--i){
H.r[1]←→H.r[i];//交换,要借用temp
HeapAdjust(H,1,i-1);//从头重建最大堆,i-1=m
}
}
HeapAdjust(r,i,m){
current=i;temp=r[i];child=2*i;
while(child<=m){//检查是否到达当前堆尾,未到尾则整理
if(child//让child指向两子女中的大者位置
if(temp.key>=r[child].key)breack;//根大则不必调整,函数结束
else{r[current]=r[child];//否则子女中的大者上移
current=child;child=2*child;}//从根降到子女位置继续向下整理!
}//while
r[current]=temp;//直到自下而上都满足堆定义,再安置函数入口的那个结点r[i](即temp)
}//HeapAdjust
1.顺序表的顺序查找
程序代码:
#include
#include
#defineMX_LENGTH100
typedefintKeyType;
typedefstruct
{
KeyType*elem;
intlength;
}SSTable;
intcreat(SSTable&L)
{
intk,i;
L.elem=(int*)malloc(MX_LENGTH*sizeof(int));
if(!
L.elem)return0;
L.length=0;
cout<<"请输入顺序表的长度:
";
cin>>k;
L.length=k;
cout<<"请输入顺序表内元素:
";
for(i=1;i<=L.length;i++)
{
cin>>L.elem[i];
}
}
intout(SSTable&L)
{
inti;
cout<<"顺序表内元素为:
";
for(i=1;i<=L.length;i++)
{
cout<}
cout<return0;
}
intSearch_Seq(SSTableST,KeyTypekey)//Search_Seqfunction
{inti;
ST.elem[0]=key;
for(i=ST.length;!
(ST.elem[i]==key);--i)
;
return(i);//ifnotfind,returni=0
}
intmain()
{
intkey,x;
SSTableL;
creat(L);
out(L);
cout<<"请输入要查找的元素:
";
cin>>key;
x=Search_Seq(L,key);
cout<<"元素在顺序表的位置为(若在顺序表中没有,为0):
";
cout<cout<cout<}
2、有序顺序表的二分查找的算法
程序代码:
#include
#include
#defineMX_LENGTH100
typedefintKeyType;
typedefstruct
{
KeyType*elem;
intlength;
}SSTable;
intcreat(SSTable&L)
{
intk,i;
L.elem=(int*)malloc(MX_LENGTH*sizeof(int));
if(!
L.elem)return0;
L.length=0;
cout<<"请输入顺序表的长度:
";
cin>>k;
L.length=k;
cout<<"请输入顺序表内元素:
";
for(i=1;i<=L.length;i++)
{
cin>>L.elem[i];
}
}
intout(SSTable&L)
{
inti;
cout<<"顺序表内元素为:
";
for(i=1;i<=L.length;i++)
{
cout<}
cout<return0;
}
intSearch_Seq(SSTableST,KeyTypekey)//Search_Seqfunction
{intmid,low=1,high=ST.length;
while(low<=high)
{mid=(low+high)/2;
if(key==ST.elem[mid])
return(mid);
elseif(keyhigh=mid-1;
else
low=mid+1;
}
return(0);
}
intmain()
{
intkey,x;
SSTableL;
creat(L);
out(L);
cout<<"请输入要查找的元素:
";
cin>>key;
x=Search_Seq(L,key);
cout<<"元素在顺序表的位置为(若在顺序表中没有,为0):
";
cout<cout<cout<}
3、二叉排序树的查找、插入、删除等基本操作的实现
程序代码:
#include
#include
#defineMX_LENGTH100
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
typedefintKeyType;
typedefcharTElemType;
/*二叉树节点的存储类型*/
typedefstructBiTNode//definestrictureBiTree
{
TElemTypedata;
structBiTNode*lchild,*rchild;
}BiTNode,*BiTree;
/*建立二叉树*/
intCreateBiTree(BiTree&T)//createBiTree()sub-function
{
TElemTypech;
cout<<"请输入二叉树结点(/为空结点):
";
cin>>ch;
if(ch=='/')T=NULL;
else
{if(!
(T=(BiTNode*)malloc(sizeof(BiTNode))))
{cout<<"Overflow!
";//noalloction
return(ERROR);
}
T->data=ch;
CreateBiTree(T->lchild);//createlchild
CreateBiTree(T->rchild);//createrchild
}
return(OK);
}//CreateBiTree()end
/*前序遍历二叉树的递归算法*/
intPreOrderTraverse(BiTreeT)//PreOrderTraverssub-function
{
if(T)
{
cout<data<<"->";//visiteT
if(PreOrderTraverse(T->lchild))//traverselchild
if(PreOrderTraverse(T->rchild))//traverserchild
return(OK);
return(ERROR);
}//ifend
else
return(OK);
}//PreOrderTraverse()end
/*中序遍历二叉树的递归算法*/
intInOrderTraverse(BiTreeT)//InOrderTraversesub-function
{
if(T)
{
if(InOrderTraverse(T->lchild))//traverselchild
{
cout<data<<"->";//visiteT
if(InOrderTraverse(T->rchild))//traverserchild
return(OK);
}
return(ERROR);
}//ifend
else
return(OK);
}//InOrderTraverse()end
/*在二叉排序树中查找某关键字等于key的数据元素*/
intSearchBST(BiTreeT,charkey,BiTreef,BiTree&p)//SearchBST()Sub-function
{if(!
T)
{p=f;
return(ERROR);
}
elseif(key==T->data)
{p=T;
return(OK);
}
elseif(keydata)
SearchBST(T->lchild,key,T,p);
else
SearchBST(T->rchild,key,T,p);
}
//二叉排序树的插入
intInsert(BiTree&T,TElemTypee)
{
BiTreep,s;
if(!
SearchBST(T,e,NULL,p))
{
s=(BiTree)malloc(sizeof(BiTNode));
s->data=e;
s->lchild=s->rchild=NULL;
if(!
p)
{
T=s;
}
elseif(edata)
{
p->lchild=s;
}
else
p->rchild=s;
returnTRUE;