数据结构实验八

南昌航空大学实验报告

0 21    6   19 

 

课程名称:     数据结构实验       实验名称:        内部排序            

班级:               姓名:               同组人:                        

指导教师评定:                                      签名:                  

 

一、 需求分析

题目:验证下列排序算法:(必做题)直接插入排序、折半插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序;(选做题)归并排序、基数排序。

1输入数据数目,随机生成数据,在根据选择哪种排序方式进行排序,输出排序以及移动次数和比较次数。

2. 演示程序以用户和计算机对话的方式进行,即在计算机终端上显示“提示信息”之后,进行输入。

3. 程序执行的命令包括:

(1) 输入数据数目;

(2) 直接插入排序;

(3) 折半插入排序;

(4) 希尔排序;

(5) 冒泡排序;

(6) 快速排序;

(7) 简单选择排序;

(8) 堆排序;

(9) 归并排序

(10) 输出

(11) 结束

二、 概要设计

1. 抽象数据类型定义

为实现上述程序功能,需要一个抽象数据类型:图。

ADT Graph{

基本操作:

InsertSort(SqList &l)

操作结果:直接插入

BInsertSort(SqList &l)

操作结果:折半插入

ShellInsert(SqList &l)

操作结果:希尔排序

SelectSort(SqList &l)

操作结果:简单选择排序

BubbleSort(SqList &l)

操作结果:冒泡排序

QuickSort(SqList &l,int low,int high)

操作结果:快速排序

mergeSort(SqList &l, int left, int right, SqList &l1)

操作结果:归并排序

HeapSort(SqList &l)

操作结果:堆排序

show(SqList l)

操作结果:输出排序后结果

Sort(SqList &l)

操作结果:选择排序方式

creat(SqList &l)

操作结果:随机生成数据

2.程序模块

1)主程序流程

void main{

   初始化结构体;

   输入数数目;

   随机生成数;

选择排序方式;

}

(2) 直接插入排序;

(3) 折半插入排序;

(4) 希尔排序;

(5) 冒泡排序;

(6) 快速排序;

(7) 简单选择排序;

(8) 堆排序;

(9) 归并排序

(10)选择排序方式

(11)随机生成数

    3.程序结构图

各模块之间的调用关系如图所示。

 

1 模块之间调用关系图

三、 详细设计

1.数据类型及结构体

typedef struct{

int r[MAXSIZE+1];//r[0]闲置或者作哨兵或作暂存单元

int length;//长度

}SqList;

void InsertSort(SqList &l){//直接插入排序

void BInsertSort(SqList &l){//折半插入排序

void ShellInsert(SqList &l){//希尔排序

void SelectSort(SqList &l){//简单选择排序

void BubbleSort(SqList &l){//冒泡排序

void QuickSort(SqList &l,int low,int high) {//快速排序

void mergeSort(SqList &l, int left, int right, SqList &l1){//归并排序

void HeapSort(SqList &l){//堆排序

void show(SqList l){//输出

void Sort(SqList &l){//选择排序方式

void creat(SqList &l){//随机生成数据

 

2.主函数

int main(){

SqList l;

printf("请输入数据总个数:");

scanf("%d",&l.length);

creat(l);

Sort(l);

return 0;

}

四、 调试分析

1.经分析冒泡排序平均时间复杂度O(n^2),选择排序平均时间复杂度O(n^2),插入排序时间复杂度为:O(n^2),希尔排序时间复杂度O(n^1.5),快速排序、堆排序、归并排序时间复杂度为O(nlogn)

2.分析各算法比较次数和移动次数如下表:

 
   

随机生成500个数据。

 

 

五、 用户手册

1. 本程序的运行环境为DOS操作系统,执行文件为:main.exe

2. 进入演示程序后即显示文本方式的用户界面。

3. 程序运行后,按照提示信息输入信息

4. 选择排序方式输出。

 

六、 测试结果

 
   

测试结果

 

 

 

 

 

 

 

 

 

七、 附录

源代码:#include<stdio.h>

#include<stdlib.h>

#include<time.h>

#define MAXSIZE 5000

typedef struct{

int r[MAXSIZE+1];//r[0]闲置或者作哨兵或作暂存单元

int length;//长度

}SqList;

 

void show(SqList);

 

void InsertSort(SqList &l){//直接插入排序

int i,j,k=0;

int move=0,compare=0;

if(l.length<2){

return;

}

for(i=2;i<=l.length;++i){

if(l.r[i]<l.r[i-1]){//前面小则说明这个数无需在排

l.r[0] = l.r[i];//r[i]放入哨兵位

move++;

l.r[i] = l.r[i-1];

move++;

for(j=i-2;l.r[0]<l.r[j];j--,compare++)//不断向前比较,比哨兵大的数后挪,小的等的停止,j+1为哨兵该放入位置

{

l.r[j+1] = l.r[j];

move++;

}

l.r[j+1] = l.r[0];

move++;

}

compare++;

if(l.length<10){

printf("%d:",++k);

show(l);

printf("\n");

}

}

printf("移动次数为:%d\n比较次数为:%d\n",move,compare);

return;

}

 

void BInsertSort(SqList &l){//折半插入排序

int i,j,k=0,low,high,m;

int move=0,compare=0;

if(l.length<2){

return;

}

for(i=2;i<=l.length;++i){

l.r[0] = l.r[i];

move++;

low = 1;

high = i-1;

while(low <= high){

m = (low+high)/2;

if(l.r[0]<l.r[m]){//大的话往小缩范围

high = m-1;

}

else{

low = m+1;

}

compare++;

}

for(j=i-1;j>=high+1;--j){//找到位置后将前面的依次往后推一位

l.r[j+1] = l.r[j];

move++;

}

l.r[high+1] = l.r[0];

move++;

if(l.length<10){

printf("%d:",++k);

show(l);

printf("\n");

}

}

printf("移动次数为:%d\n比较次数为:%d\n",move,compare);

return;

}

 

void ShellInsert(SqList &l){//希尔排序

int i,j,k=0,gap,temp;

int move=0,compare=0;

if(l.length<2){

return;

}

for (gap = l.length/2;gap>0;gap/=2){//增量设为gap起始为length/2

        for (i = gap;i<=l.length;i++){

            j = i;

            temp = l.r[j];

            if (l.r[j]<l.r[j-gap]){

            while(j-gap>0 && temp<l.r[j-gap]){//用于排除第一个和r[0]比较的交换,同时找到插入temp的位置  

                compare++;

                l.r[j] = l.r[j-gap];

                move++;

                j = j-gap;

            }

            compare++;

            l.r[j] = temp;

            move++;

            }

        }

        if(l.length<10){

        printf("%d:",++k);

show(l);

printf("\n");

}

    }

    printf("移动次数为:%d\n比较次数为:%d\n",move,compare);

    return;

}

 

void SelectSort(SqList &l){//简单选择排序

int i,j,k,temp,flag;

int move=0,compare=0;

if(l.length<2){

return;

}

for(i=1;i<=l.length;i++){//不断找最排序的最小的

    flag=i;

    l.r[0]=l.r[i];

    move++;

for(j=i;j<=l.length;j++,compare++){

if(l.r[0]>l.r[j]){

l.r[0]= l.r[j];

move++;

flag=j;

}

}

l.r[flag]=l.r[i];

move++;

l.r[i]=l.r[0];

move++;

if(l.length<10){

printf("%d:",++k);

show(l);

printf("\n");

}

}

    printf("移动次数为: %d\n",move);

    printf("比较次数为: %d\n",compare);

return;

}

 

void BubbleSort(SqList &l){//冒泡排序

int i,j,k,flag,temp;

int move=0,compare=0;

if(l.length<2){

return;

}

for(i=1;i<=l.length;i++){

flag = 0;//是否经过移动,未经移动则说明后面已经排好没必要继续

for(j=1;j<=l.length-i;j++){

if(l.r[j+1]<l.r[j]){

flag = 1;

temp= l.r[j];

l.r[j] = l.r[j+1];

l.r[j+1] = temp;

move++;

move++;

}

compare++;

}

if(flag==0){

printf("移动次数为: %d\n",move);

printf("比较次数为: %d\n",compare);

return;

}

if(l.length<10)

{

printf("%d:",++k);

show(l);

printf("\n");

}

 

}

 

return;

}

int Quickmove=0,Quickcompare=0;

void QuickSort(SqList &l,int low,int high) {//快速排序

int i,j,key;                             //选第一个做基准

if(low < high){

        i   = low;

        j   = high;

        key = l.r[i];

        while(i < j){                         //不断缩拢 范围i-j

            while(i < j && l.r[j] >= key){// 从右向左找第一个小于key的数,记录这个点 j

                j--;

                Quickcompare++;

            }

            if (i < j){

             l.r[i] = l.r[j];

             Quickmove++;

            }

            while(i < j && l.r[i] < key){//从左向右找第一个大于等于key的数,记录这个点i

                i++;

                Quickcompare++;

            }

            

            if (i < j){

                l.r[j] = l.r[i];

                Quickmove++;

            }

        }

        l.r[i] = key;

        Quickmove++;

        QuickSort(l, low, i - 1);

        QuickSort(l, i + 1, high);

    }

}

int mergecompare=0,mergemove=0;

void merge(SqList &l , int left, int mid, int right,SqList &l1){

int i = left;  //初始化i,左边有序序列的初始索引

int j = mid + 1;  //初始化j,右边有序序列的初始索引

int t = 0;  //指向temp数组的当前索引

while(i <= mid && j<= right)

{

if(l.r[i] <= l.r[j])

{

l1.r[t] = l.r[i];

i++;

t++;

}

else  //反之右边的小于左边的当前元素

{

l1.r[t] = l.r[j];

j++;

t++;

}

mergecompare++,mergemove++;

}

while(i <= mid)

{

l1.r[t] = l.r[i];

t++;

i++;

mergemove++;

}

while(j <= right)  //右边有剩余

{

l1.r[t] = l.r[j];

j++;

t++;

mergemove++;

}

t = 0;

int tempLeft = left;

while(tempLeft <= right)

{

l.r[tempLeft] = l1.r[t];

t++;

tempLeft++;

mergemove++;

}

}

 

void mergeSort(SqList &l, int left, int right, SqList &l1){//归并排序

if(left < right)

{

int mid = (left + right) / 2;

//向左进行递归分解

mergeSort(l, left, mid, l1);

//向左进行递归分解

mergeSort(l, mid + 1, right, l1);

//合并

merge(l, left, mid, right, l1);

}

}

int Heapcompare=0,Heapmove=0;

void HeapAdjust(SqList &l, int s, int length) {

    int temp,i,j;

    temp =  l.r[s];

    for(j=2*s;j<=length;j*=2){//找到非叶子结点的两个子节点,把三者中最大的换到非叶子节点内

     if(j<length &&(l.r[j]<l.r[j+1])){

     ++j;

}

Heapcompare++;

if(temp>=l.r[j]){

Heapcompare++;

break;

}

l.r[s] = l.r[j];

Heapmove++;

s = j;

}

l.r[s] = temp;

Heapmove++;

}

 

void HeapSort(SqList &l){//堆排序

   int i;

for(i=l.length/2;i>0;--i){

HeapAdjust(l,i,l.length);

}

for(i=l.length;i>1;--i){//把第一个最大的往后放

int temp = l.r[i];

l.r[i] = l.r[1];

Heapmove++;

l.r[1] = temp;

Heapmove++;

HeapAdjust(l,1,i-1);//不断把未排序的最大的放到第一个

}

}

 

void show(SqList l){

int i;

printf("最终排序为:");

for(i=1;i<=l.length;i++){

printf("%d ",l.r[i]);

}

printf("\n");

}

 

void Sort(SqList &l){

int a;

SqList l1,l2;

printf("0.结束 1.直接插入 2.折半插入 3.希尔 4.冒泡 5.快速排序 6.简单选择 7.8.归并\n请输入:\n");

scanf("%d",&a);

while(a!=0){

l1 = l;

switch(a){

case 1:InsertSort(l1);break;

case 2:BInsertSort(l1);break;

case 3:ShellInsert(l1);break;

case 4:BubbleSort(l1);break;

case 5:QuickSort(l1,1,l1.length);printf("移动次数为:%d\n比较次数为:%d\n",Quickmove,Quickcompare);break;

case 6:SelectSort(l1);break;

case 7:HeapSort(l1);printf("移动次数为:%d\n比较次数为:%d\n",Heapmove,Heapcompare);break;

case 8:l2 = l1; mergeSort(l1,1,l.length,l2);printf("移动次数为:%d\n比较次数为:%d\n",mergemove,mergecompare);break;

}

printf("\n");

show(l1);

printf("\n0.结束 1.直接插入 2.折半插入 3.希尔 4.冒泡 5.快速 6.简单选择 7.8.归并\n请输入:\n");

scanf("%d",&a);

}

}

 

void creat(SqList &l){

int i,a1;

     srand(time(NULL));

    printf("输入要排序的数:");

for(i=1;i<=l.length;i++){

a1=rand()%(10000)+1;//随机生成一个[1,10000)区间内的整数

//scanf("%d",&a1);

l.r[i] = a1;

}

}

 

int main(){

SqList l;

printf("请输入数据总个数:");

scanf("%d",&l.length);

creat(l);

Sort(l);

return 0;

}

 

posted @ 2022-03-14 23:18  安良  阅读(544)  评论(0)    收藏  举报