数据结构排序实验


实验五 排序实验

实验目的

熟练掌握各种排序算法的实现方法,以及不同算法的特点,掌握各种排序方法的时间效率。

1、排序比较

问题描述

各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间。对一组给定的数据,采用各不同排序算法对其进行排序,给出各算法在排序中的关键字比较次数和关键字移动次数,以取得直观感受。

基本要求

(1)对以下各排序算法进行比较:直接插入排序、冒泡排序、快速排序、简单选择排序、归并排序。

(2)待排序表的表长为100;对每组数据用以上各排序方法进行排序,比较的指标为有关键字参加的比较次数和关键字的移动次数。

实现提示

在算法的适当地方加入计数操作,计算关键字的比较次数和移动次数。

Input

输入部分第一行为待排关键字的个数n,第二行为n个待排关键字,所有数据之间由空格分隔。

Output
输出共1行,共有10个整数,表示5种排序方法排序的关键字比较次数和移动次数,即为:直接插入排序比较次数、直接插入排序移动次数、冒泡排序比较次数、冒泡排序移动次数、快速排序比较次数、快速排序移动次数、简单选择排序比较次数、简单选择排序移动次数、归并排序比较次数、归并排序移动次数。

Sample Input

5

1 2 3 4 5

Sample Output

4 0  4 0  10 16  10 0  7 17

Sample Input

5

5 4 3 2 1

Sample Output

14 18  10 30  12 16  10 6  5 17

需求分析:(包括对问题的理解,解决问题的策略、方法描述)

直接插入排序:基本思想:将一个记录插入到已排好序的有序表中,得到新

               的表依然有序。

将序列中第1个记录看成是一个有序子序列,从第2个记录开始到第n个记录,逐个进行插入,直至整个序列有序

冒泡排序:基本思想:

          对n个记录,依次比较相邻两个关键字,不满足条件,则交换-----一趟冒泡排序,对前n-1个记录作第二趟排序,重复共作n-1趟。

快速排序:基本思想:通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录进行排序,以达到整个序列有序

简单选择排序:基本思想:每一趟在n-i+1(i=1,2…,n-1)个记录中选择关键

              字最小的记录作为有序序列中第i个记录。

归并排序:归并:将两个或两个以上的有序表组合成一个新的有序表

系统设计:(包括数据结构定义、抽象出基本操作描述、主程序模块处理过程描述)

typedef struct

{

int *r;

int length;

int listsize;

}Sqlist;

struct num

{

int compare;

int move;

};

int Init_Sq(Sqlist &L)

{

L.r = (int*)malloc(100*sizeof(int));

if(!L.r) exit(0);

L.length=1;

L.listsize =100;

L.r[0]=0;

return 1;

}

//第i个元素之前插入新元素

void InsertSq(Sqlist &L,int i,int key)

{

int *p,*q;

q=&(L.r[i-1]);

for(p=&(L.r[L.length-1]);p>=q;--p)

*(p+1)=*p;

*q=key;

L.length++;

创建顺序表 存储数据 设立结构e 包含比较次数和移动次数

基本操作的实现:(对各基本操作实现的描述)

#include<stdio.h>

#include<stdlib.h>

typedef struct

{

int *r;

int length;

int listsize;

}Sqlist;

struct num

{

int compare;

int move;

};

int Init_Sq(Sqlist &L)

{

L.r = (int*)malloc(100*sizeof(int));

if(!L.r) exit(0);

L.length=1;

L.listsize =100;

L.r[0]=0;

return 1;

}

//第i个元素之前插入新元素

void InsertSq(Sqlist &L,int i,int key)

{

int *p,*q;

q=&(L.r[i-1]);

for(p=&(L.r[L.length-1]);p>=q;--p)

*(p+1)=*p;

*q=key;

L.length++;

}

//直接插入排序

void InsertSort(Sqlist &L,num &e)

{

int i,j;

for(i=2;i<L.length;i++)

{

e.compare++;

if(L.r[i]<L.r[i-1])

{

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

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

e.move=e.move+2;

for(j=i-2;L.r[0]<L.r[j];j--)

{

e.compare++;

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

e.move=e.move+1;

}

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

e.move++;

e.compare++;//最后一次不满足条件的比较

}

}

}

//冒泡排序

void sort(Sqlist &L,num &e)

{

int i,flag,j;

for(i=1;i<=L.length-1;i++)

  {

flag=0;

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

{

e.compare++;

if(L.r[j]>L.r[j+1])

{

int t;

t=L.r[j];

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

L.r[j+1]=t;

flag=1;

e.move=e.move+3;//算移动三次

}

}

if(!flag) break;

}

}

//快速排序

//完成一趟排序

int Partition(Sqlist &L,int low,int high,num &e)

{

int pivokey;

L.r[0]=L.r[low];//也算一次移动!

e.move++;

pivokey=L.r[low];

while(low<high)//只计关键字比较次数 low与high比较不算

{

while(low<high&&L.r[high]>=pivokey)

{

high--;

e.compare++;

}

if(low<high)

{

e.compare++;

}

L.r[low]=L.r[high];

e.move++;

while(low<high&&L.r[low]<=pivokey)

{

low++;

e.compare++;

}

if(low<high)

{

e.compare++;

}

L.r[high]=L.r[low];

e.move=e.move+1;

}

L.r[low]=L.r[0];

e.move++;

return low;

}

void Qsort(Sqlist &L,int low,int high,num &e)

{

int pivotloc;

if(low<high)

{

pivotloc = Partition(L,low,high,e);

Qsort(L,low,pivotloc-1,e);

Qsort(L,pivotloc+1,high,e);

}

 }

 //简单选择排序

 int SelectMinkey(Sqlist &L,int i,num &e)

 {//选择L[i...L.length-1]中最小的

  int m,min=L.r[i],sta;

  sta=i;

  for(m=i+1;m<L.length;m++)

  {

  e.compare++;

  if(L.r[m]<min)

  {

  min=L.r[m];

  sta=m;

    }

 }

 return sta;

 }

  void SelectSort(Sqlist &L,num &e)

  {

   int i,j;

   for(i=1;i<L.length;i++)

   {

  

   j=SelectMinkey(L,i,e);

  

   if(i!=j)//比较i,j不计入比较次数

   {

   int t;

   t=L.r[i];

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

   L.r[j]=t;

   e.move=e.move+3;//算移动三次

}

}

  }

  //归并排序

  int TR1[100];

  void Merge(int SR[],int TR1[],int i,int m,int n,num &e)

  {

   int j,k;

   for ( j = m + 1 , k = i ; i <= m && j <= n ; k++ )

  {

        e.compare++;

      if  (SR[ i ]<SR[ j ])

      {

    TR1[ k ] = SR[ i ++ ] ;

  e.move++;

  

      }

      else

  {  

    TR1[ k ] = SR[ j ++ ] ;

    e.move++;

  

     }

  }

  

  if ( i <= m )  

  {

   while(i<=m)

   {

   TR1[k++]=SR[i++];

   e.move++;

  }

  }

  

  if ( j <= n )  

  {

   while(j<=n)

   {

   TR1[k++]=SR[j++];

   e.move++;

  }

  }

  }

  void MSort(int SR[],int TR1[],int s,int t,num &e)

  {

   int TR2[100];

   int m;

   if(s==t)

   {

  TR1[s]=SR[s] ;

  e.move++;

    }

   else

   {

   m=(s+t)/2;//平分SR

   MSort(SR,TR2,s,m,e); //前一半归并为有序的TR2[s...m]

   MSort(SR,TR2,m+1,t,e);// 后一半归并为有序的TR2[m+1..t]

   Merge(TR2,TR1,s,m,t,e);//TR2归并到TR1

}

  }

  void MergeSort(Sqlist &L,num &e)

  {

   MSort(L.r,L.r,1,L.length-1,e);

  }int main()

{

int n;

int a[101];

num e;

Sqlist L1,L2,L3,L4,L5;

scanf("%d",&n);

int i,j;

Init_Sq(L1);

Init_Sq(L2);

Init_Sq(L3);

Init_Sq(L4);

Init_Sq(L5);

for(i=n-1;i>=0;i--)

{

scanf("%d",&a[i]);

}

//直接插入排序

e.move=0;

e.compare=0;

for(i=1;i<=n;i++)

{

InsertSq(L1,2,a[i-1]);

}

InsertSort(L1,e);

printf("%d %d ",e.compare,e.move);

//冒泡排序

e.move=0;

e.compare=0;

for(i=1;i<=n;i++)

{

InsertSq(L2,2,a[i-1]);

}

sort(L2,e);

printf("%d %d ",e.compare,e.move);

//快速

e.move=0;

e.compare=0;

for(i=1;i<=n;i++)

{

InsertSq(L3,2,a[i-1]);

}

Qsort(L3,1,n,e);

printf("%d %d ",e.compare,e.move);

// 简单选择

e.move=0;

e.compare=0;

for(i=1;i<=n;i++)

{

InsertSq(L4,2,a[i-1]);

}

SelectSort(L4,e);

printf("%d %d ",e.compare,e.move);

//归并

e.move=0;

e.compare=0;

for(i=1;i<=n;i++)

{

InsertSq(L5,2,a[i-1]);

}

MergeSort(L5,e);

printf("%d %d",e.compare,e.move);

return 0;

 }

测试结果:(输入的测试数据及运行结果、正确性、在线测试情况)

调试分析:(包括调试过程中对原设计的修改,以及遇到的问题和解决的方法)

注意输出格式就好。

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光而不耀-2001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值