数据结构习题解析与实训 第九章.docx
《数据结构习题解析与实训 第九章.docx》由会员分享,可在线阅读,更多相关《数据结构习题解析与实训 第九章.docx(30页珍藏版)》请在冰豆网上搜索。
![数据结构习题解析与实训 第九章.docx](https://file1.bdocx.com/fileroot1/2023-4/17/01da3038-6be2-49cd-a6bb-276e8f712ccc/01da3038-6be2-49cd-a6bb-276e8f712ccc1.gif)
数据结构习题解析与实训第九章
第
9
章内部排序
以下内部排序的各种算法中,排序对象的数据元素表采用顺序存储结构。
为简单起
见,表的最大容量为100,每个元素只包含一个字段即关键字段,且关键字都是整型值。
排序表的结构如下所示。
#define KEYTYPE int
#define MAXSIZE 100
typedef struct
{KEYTYPE key;
}RECNODE;
RECNODE a[MAXSIZE];
9.1
习题解析
【习题
1
】 直接插入排序
题目要求:
将输入的若干个整数按直接插入排序算法从小到大排序,数据从数组的1
单元放起。
【解答】
#include ″datastru.h″
#include
voidinsertsort(RECNODE*r,intn)
{/*直接插入排序*/
inti,j;
for(i=2;i<=n;i++)
{[0]=r[i];j=i-1; /*r[0]是监视哨,j表示当前已排好序列的长度*/
l110
数据结构习题解析与实训
while(r[0].key {r[j+1]=r[j]; j--;}
r[j+1]=r[0];/*元素插入*/
}
}
main()
{ECNODE a[MAXSIZE];
int i,j,k,len;
printf(″\n\n输入待排序数据(整数,以空格隔开,′0′结束):
″);k=0;scanf(″%d″,&j);
while(j!
=0){k++;a[k].key=j;scanf(″%d″,&j);}
len=k;
printf(″\n排序前:
″);
for(i=0;iprintf(″\n″);
insertsort(a,len);
printf(″\n\n排序后:
″);
for(i=0;iprintf(″\n\n″);
}
【习题
2
】 冒泡排序
题目要求:
将输入的若干个整数按冒泡排序算法从小到大排序,数据从数组的1单
元放起。
【解答】
#include ″datastru.h″
#include
voidbublesort(RECNODE*r,intn)
{/*简单交换排序:
冒泡排序*/
inti,j;
RECNODEtemp;
for(i=1;i for(j=n-1;j>=i;j--)
if(r[j+1].key {temp=r[j+1]; r[j+1]=r[j]; r[j]=temp;}
}
main()
{ECNODE a[MAXSIZE];
第9章 内部排序
l111
int i,j,k,len;
printf(″\n\n输入待排序数据(整数,以空格隔开,′0′结束):
″);k=0;scanf(″%d″,&j);
while(j!
=0){k++;a[k].key=j;scanf(″%d″,&j);}
len=k;
printf(″\n排序前:
″);
for(i=0;iprintf(″\n″);
bublesort(a,len);
printf(″\n\n排序后:
″);
for(i=0;iprintf(″\n\n″);
}
【习题
3
】 简单选择排序
题目要求:
将输入的若干个整数按简单选择排序算法从小到大排序,数据从数组的1
单元放起。
【解答】
#include ″datastru.h″
#include
voidselesort(RECNODE*r,intn)
{/*简单选择排序*/
inti,j,k;
RECNODEtemp;
for(i=1;i {=i; /*k:
最小关键字的初始位置*/
for(j=i+1;j<=n;j++)
if(r[j].keyk=j;/*k:
跟踪记录当前最小关键字的位置*/
if(k!
=i)/*最小关键字元素和待排序列的第一个元素交换*/
{temp=r[i]; r[i]=r[k]; r[k]=temp;}
}
}
main()
{ECNODE a[MAXSIZE];
int i,j,k,len;
printf(″\n\n输入待排序数据(整数,以空格隔开,′0′结束):
″);k=0;scanf(″%d″,&j);
l112
数据结构习题解析与实训
while(j!
=0){k++;a[k].key=j;scanf(″%d″,&j);}
len=k;
printf(″\n排序前:
″);
for(i=0;iprintf(″\n″);
selesort(a,len);
printf(″\n\n排序后:
″);
for(i=0;iprintf(″\n\n″);
}
【习题
4
】 快速排序
题目要求:
将输入的若干个整数按快速排序算法从小到大排序,数据从数组的1单
元放起。
【解答】
#include ″datastru.h″
#include
intpartition(RECNODE*r,int*low,int*high)
{/*一趟快速排序,返回枢轴位置,产生两个独立的待排子序列*/
inti,j;
RECNODEtemp;
i=*low; j=*high;
temp=r[i]; /*枢轴记录保存在temp变量中*/
do{hile((r[j].key>=temp.key)&&(iif(i while((r[i].key<=temp.key)&&(i if(i }while(i!
=j);
r[i]=temp;/*枢轴记录的排序位置确定在i*/
returni;
}
voidquicksort(RECNODE*r,intstart,intend)
{/*快速排序*/
inti;
if(start {i=partition(r,&start,&end);/*一趟快速排序,返回枢轴位置,产生两个独立的待排子
序列*/
quicksort(r,start,i-1);/*对两个独立的待排子序列分别递归调用快速排序算法*/
第9章 内部排序
l113
quicksort(r,i+1,end);}
}
main()
{ECNODE a[MAXSIZE];
int i,j,k,len,start;
printf(″\n\n输入待排序数据(整数,以空格隔开,′0′结束):
″);k=0;scanf(″%d″,&j);
while(j!
=0){k++;a[k].key=j;scanf(″%d″,&j);}
len=k;start=1;
printf(″\n排序前:
″);
for(i=0;iprintf(″\n″);
quicksort(a,start,len);
printf(″\n\n排序后:
″);
for(i=0;iprintf(″\n\n″);
}
【习题
5
】 堆排序
题目要求:
将输入的若干个整数按堆排序算法从小到大排序,数据从数组的1单元
放起。
【解答】
#include ″datastru.h″
#include
voidsift(RECNODE*r,inti,intm)
{/*i是根结点编号,m是以i结点为根的子树中最后一个结点的编号*/
intj;
RECNODEtemp;
temp=r[i];
j=2*i; /*j为i根结点的左孩子*/
while(j<=m)
{if(j j++;/*当i结点有左右孩子时,j取关键字大的孩子结点编号*/
if(temp.key {r[i]=r[j]; i=j; j=2*i;} /*按堆定义调整,并向下一层筛选调整*/
else break;/*筛选调整完成,跳出循环*/
}
r[i]=temp;
l114
数据结构习题解析与实训
}
voidheapsort(RECNODE*r,intn)
{/*堆排序:
n为r表中记录数,元素从r[1]开始放起*/
inti;
RECNODEtemp;
for(i=n/2;i>=1;i--)
sift(r,i,n); /*将无序序列建成大堆*/
for(i=n;i>=2;i--)
{temp=r[1];/*堆顶及堆尾元素交换*/
r[1]=r[i];
r[i]=temp;
sift(r,1,i-1);/*交换后,从第一个元素开始调整为大堆,每次要处理的记录个数少一个*/
}
}
main()
{ECNODE a[MAXSIZE];
int i,j,k,len;
printf(″\n\n输入待排序数据(整数,以空格隔开,′0′结束):
″);k=0;scanf(″%d″,&j);
while(j!
=0){k++;a[k].key=j;scanf(″%d″,&j);}
len=k;
printf(″\n排序前:
″);
for(i=0;iprintf(″\n″);
heapsort(a,len);
printf(″\n\n排序后:
″);
for(i=0;iprintf(″\n\n″);
}
【习题
6
】 二路归并排序
题目要求:
将输入的若干个整数按二路归并排序算法从小到大排序,数据从数组的0
单元放起。
【解答】
#include ″datastru.h″
#include
voidmerge(RECNODE*r,intlow,intm,inthigh)
{/*两相邻的有序表(一个从low到m;另一个从m+1到high)合并为一个有序表(从low到
第9章 内部排序
l115
high)*/
RECNODE r1[MAXSIZE]; /*合并时用的缓冲向量*/
inti,j,k;
i=low;
j=m+1;
k=0;
while(i<=m&&j<=high)/*两相邻的有序表合并*/
if(r[i].key<=r[j].key)
{r1[k]=r[i]; i++; k++;}
else
{r1[k]=r[j]; j++; k++;}
while(i<=m)/*有序表剩余部分处理*/
{r1[k]=r[i]; i++; k++;}
while(j<=high)/*有序表剩余部分处理*/
{r1[k]=r[j]; j++; k++;}
for(i=low,k=0;i<=high;i++,k++)/*缓冲向量r1复制到原来的r中*/
r[i]=r1[k];
}
voidmerge_one(RECNODE*r,intlenth,intn)
{/*二路归并中的″一趟归并″算法*/
inti=0;
while(i+2*lenth-1 {merge(r,i,i+lenth-1,i+2*lenth-1); /*两子序列长度相等的*/
i=i+2*lenth;}/*情况下调用merge*/
if(i+lenth-1 merge(r,i,i+lenth-1,n-1);/*序列中的余留部分处理*/
}
voidmergesort(RECNODE*r,intn)
{/*二路归并排序算法*/
intlenth=1; /*有序子序列长度初始值=1*/
while(lenth {merge_one(r,lenth,n);/*调用″一趟归并″的算法*/
lenth=2*lenth;}/*有序子序列长度加倍*/
}
main()
{ECNODE a[MAXSIZE];
int i,j,k,len;
l116
数据结构习题解析与实训
printf(″\n\n输入待排序数据(整数,以空格隔开,′0′结束):
″);k=0;scanf(″%d″,&j);
while(j!
=0){k++;a[k-1].key=j;scanf(″%d″,&j);}
len=k;
printf(″\n排序前:
″);
for(i=0;iprintf(″\n″);
mergesort(a,len);
printf(″\n″);
printf(″\n\n排序后:
″);
for(i=0;iprintf(″\n″);
}
【习题
7
】 排序综合练习
这是一个将上面的各个排序算法合并在一个综合程序中的练习,读者可通过菜单选
择方式运行各个排序算法。
【解答】
#include
#include ″datastru.h″
intcreateList(RECNODE*r)
{ntj,k;
printf(″\n\n输入待排序数据(整数,以空格隔开,′0′结束):
″);k=0;scanf(″%d″,&j);
while(j!
=0){k++;r[k].key=j;scanf(″%d″,&j);}
returnk;
}
frontdisplayList(RECNODE*r,intn)
{nti;
printf(″\n排序前:
″);
for(i=0;iprintf(″\n\n″);
}
reardisplayList(RECNODE*r,intn)
{nti;
printf(″\n\n排序后:
″);
第9章 内部排序
l117
for(i=0;iprintf(″\n\n″);
}
voidinsertsort(RECNODE*r,intn)
{/*直接插入排序*/
inti,j;
for(i=2;i<=n;i++)
{[0]=r[i]; j=i-1; /*r[0]是监视哨,j表示当前已排好序列的长度*/
while(r[0].key {r[j+1]=r[j]; j--;}
r[j+1]=r[0];/*元素插入*/
}
}
voidbublesort(RECNODE*r,intn)
{/*简单交换排序:
冒泡排序*/
inti,j;
RECNODEtemp;
for(i=1;i for(j=n-1;j>=i;j--)
if(r[j+1].key {temp=r[j+1]; r[j+1]=r[j]; r[j]=temp;}
}
intpartition(RECNODE*r,int*low,int*high)
{/*一趟快速排序,返回i,产生了两个独立的待排子序列*/
inti,j;
RECNODEtemp;
i=*low; j=*high;
temp=r[i]; /*枢轴记录保存在temp变量中*/
do{hile((r[j].key>=temp.key)&&(iif(iwhile((r[i].key<=temp.key)&&(iif(i }while(i!
=j);
r[i]=temp;/*枢轴记录的排序位置确定在i*/
returni;
}
l118
数据结构习题解析与实训
voidquicksort(RECNODE*r,intstart,intend)
{/*快速排序*/
inti;
if(start {i=partition(r,&start,&end);
/*一趟快速排序,返回i,产生了两个独立的待排子序列*/
quicksort(r,start,i-1);/*对两个独立的待排子序列分别递归调用快速排序算法*/
quicksort(r,i+1,end);}
}
voidselesort(RECNODE*r,intn)
{/*简单选择排序*/
inti,j,k;
RECNODEtemp;
for(i=1;i {=i; /*k:
最小关键字的初始位置*/
for(j=i+1;j<=n;j++)
if(r[j].keyk=j;/*k:
跟踪记录当前最小关键字的位置*/
if(k!
=i)/*最小关键字元素和待排序列的第一个元素交换*/
{temp=r[i]; r[i]=r[k]; r[k]=temp;}
}
}
voidsift(RECNODE*r,inti,intm)
{/*i是根结点编号,m是以i结点为根的子树中最后一个结点的编号*/
intj;
RECNODEtemp;
temp=r[i];
j=2*i;/*j为i根结点的左孩子*/
while(j<=m)
{if(j j++; /*当i结点有左右孩子时,j取关键字大的孩子结点编号*/
if(temp.key {r[i]=r[j]; i=j; j=2*i;}/*按堆定义调整,并向下一层筛选调整*/
else break;/*筛选调整完成,跳出循环*/
}
r[i]=temp;
}
第9章 内部排序
l119
voidheapsort(RECNODE*r,intn)
{/*堆排序:
n为r表中记录数,元素从r[1]开始放起*/
inti;
RECNODEtemp;
for(i=n/2; i>=1; i--)
sift(r,i,n);/*将无序序列建成大堆*/
for(i=n; i>=2; i--)
{temp=r[1];/*堆顶及堆尾元素交换*/
r[1]=r[i];
r[i]=temp;
sift(r,1,i-1); /*交换后,从第一个元素开始调整为大堆,每次要处理的记录个数减
少一个*/
}
}
voidmerge(RECNODE*r,intlow,intm,inthigh)
{/*两相邻的有序表(一个从low到m;另一个从m+1到high)合并为一个有序表(从low到
high)*/
RECNODE r1[MAXSIZE];/*合并时用的缓冲向量*/
inti,j,k;
i=low;
j=m+1;
k=0;
while(i<=m&&j<=high)/*两相邻的有序表合并*/
if(r[i].key<=r[j].key)
{r1[k]=r[i]; i++; k++;}
else
{r1[k]=r[j]; j++; k++;}
while(i<=m)/*有序表剩余部分处理*/
{r1[k]=r[i]; i++; k++;}
while(j<=high)/*有序表剩余部分处理*/
{r1[k]=r[j]; j++; k++;}
for(i=low,k=0;i<=high;i++,k++) /*缓冲向量r1复制到原来的r中*/
r[i]=r1[k];
}
voidmerge_one(RECNODE*r,intlenth,intn)
{/*二路归并中的″一趟归并″算法*/
inti=0;
while(i+2*lenth-1l120
数据结构习题解析与实训
{merge(r,i,i+lenth-1,i+2*lenth-1); /*两子序列长度相等的*/
i=i+2*lenth;}/*情况下调用merge*/
if(i+lenth-1 merge(r,i,i+lenth-1,n-1);/*序列中的余留部分处理*/
}
voidmergesort(RECNODE*r,intn)
{/*二路归并排序算法*/
intlenth=1;/*有序子序列长度初始值=1*/
while(lenth {merge_one(r,lenth,n);/*调用″一趟归并″的算法*/
lenth=2*lenth;}/*有序子序列长度加倍*/
}
voidmain(){
RECNODE a[MAXSIZE];
intlen,b,j,k;
intloop=1;
while(loop){
printf(″\n\n排序综合练习\n\n″);
printf(″ 0--退出\n″);
printf(″ 1--直接插入排序\n″);
printf(″ 2--简单交换(冒泡)排序\n″);
printf(″ 3--快速排序\n″);
printf(″ 4--简单选择排序\n″);
printf(″ 5--堆排序\n″);
printf(″ 6--二路归并排序\n″);
printf(″\n\n请选择项号:
″);
scanf(″%d″,&b);
printf(″\n\n″);
if(b>=0&&b<=6)
switch(b){
case0:
loop=0;
break;