数据结构----各种排序算法的比较

一.实验目的

   实现常用的排序算法,加深对这些算法的理解,以后可以将这些算法应用到实际问题的解决上。


 二.实验题目

排序是在实际问题中经常用到的算法,快速、选择和插入三种排序算法是排序算法中最简单的也是最常用到的,实现这三种算法,在不同的数值序列上运行,然后比较三种方法的空间复杂度和时间复杂度,分析比较结果,得出选择这三种排序算法的一般原则。


三.实现提示

1.待排序列的数据结构描述:

[cpp]  view plain  copy
  1. #define   MAXSIZE     20       //一个用作示例的顺序表的最大长度  
  2.         typedef   int   KeyType;           //定义关键字类型为整数类型  
  3.      typedef  struct   
  4.  {  
  5.       KeyType    key;                 //关键字项  
  6.    InfoType    otherifo;          //其他数据项  
  7.  }RedType;                    //记录类型  
  8.  typedef struct  
  9.  {  
  10.       RedType  r[MAXSIZE+1];      //r[0]闲置或用作哨兵单元  
  11.       int       length;              //顺序表的长度  
  12.  }SqList;                      //顺序表类型  
  13.    

2.待排序列应该考虑多种情况,例如基本有序以及基本无序的情况等,这样才能得到在不同的数据情况下算法优劣性的比较。


 四.思考及选做

  1.进一步探讨其他的排序算法的比较,得出类似的时间复杂度以及空间复杂度的分析,特别要注意针对不同的算法,测试数据的结构也要尽可能的丰富。


五.我的实现

 (1)  排序算法的实现

[cpp]  view plain  copy
  1. #include<stdio.h>  
  2.  #include<stdlib.h>  
  3.  #define MAXSIZE 20      //一个用作示例的顺序表的最大长度  
  4.    
  5.  /*************************************数据结构的定义*************************************/  
  6.  typedef int KeyType;         //定义关键字类型为整数类型  
  7.  typedef char InfoType;   
  8.  typedef  struct   
  9.  {  
  10.     KeyType key;              //关键字项  
  11.     InfoType otherifo;        //其他数据项  
  12.  }RedType;                    //记录类型  
  13.    
  14.  typedef struct  
  15.  {  
  16.     RedType r[MAXSIZE+1];      //r[0]闲置或用作哨兵单元  
  17.     int length;                //顺序表的长度  
  18.  }SqList;                      //顺序表类型  
  19.    
  20.    
  21.  /****************************************功能函数*****************************************/  
  22.  /* 
  23.    快速排序.  
  24.    思想:选定一个枢纽元素,对待排序序列进行分割, 
  25.    分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再 
  26.    对这两个分割好的子序列进行上述的过程。 
  27.    总结:平均效率O(nlogn),适用于排序大列表。  
  28.    此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能 
  29.    导致O(n2)的最糟用例效率。若数基本有序,效率反而最差。选项中间 
  30.    值作为枢纽,效率是O(nlogn)。基于分治法。   
  31.  */  
  32.  void QuickSort(SqList &L,int l,int h)  
  33.  {  
  34.     if (l>=h)  
  35.        return ;  
  36.     int j ,i,key;  
  37.     i=l;  
  38.     j=h;  
  39.     key=L.r[i].key;  
  40.     while(i<j)  
  41.       {  
  42.          while(i<j&&L.r[j].key>key)  
  43.             j--;  
  44.          if (i<j)  
  45.             L.r[i++].key=L.r[j].key;  
  46.          while (i<j&&L.r[i].key<key)  
  47.             i++;  
  48.          if (i<j)  
  49.             L.r[j--].key=L.r[i].key;  
  50.       }  
  51.      L.r[i].key=key;  
  52.      if (l<i-1)  
  53.          QuickSort(L,l,i-1);  
  54.      if (i+1<h)  
  55.          QuickSort(L,i+1,h);  
  56.     
  57.  }  
  58.    
  59.  /* 
  60.    选择排序。  
  61.    思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序 
  62.    放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。  
  63.  */  
  64.  void SelectSort(SqList &L)      
  65.  {  
  66.      int i,j,m,n=L.length+1 ;  
  67.      int t ;                //临时变量  
  68.      for(i=1;i<n;i++)      
  69.      {  
  70.          m=i ;  
  71.          for(j=i+1;j<n;j++)      
  72.          {  
  73.              if(L.r[j].key<L.r[m].key)  
  74.                 m=j;          
  75.          }  
  76.          if(m!=i)      
  77.          {  
  78.              t=L.r[i].key;  
  79.              L.r[i].key=L.r[m].key;  
  80.              L.r[m].key=t ;  
  81.          }  
  82.      }  
  83.            
  84.  }  
  85.    
  86.  /* 
  87.    插入排序。 
  88.    思想:将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。  
  89.    最佳效率O(n);最糟效率O(n2)与冒泡、选择相同,适用于排序小列表  
  90.    若列表基本有序,则插入排序比冒泡、选择更有效率。  
  91.  */  
  92.  void InsertSort(SqList &L)  
  93.  {  
  94.    // 对顺序表L作直接插入排序。  
  95.    int i,j;  
  96.    for (i=2; i<=L.length; ++i)  
  97.      if (L.r[i].key<L.r[i-1].key)  
  98.      {  
  99.        // "<"时,需将L.r[i]插入有序子表  
  100.        L.r[0] = L.r[i];                 // 复制为哨兵  
  101.        for (j=i-1;  L.r[0].key<L.r[j].key;  --j)  
  102.          L.r[j+1] = L.r[j];             // 记录后移  
  103.        L.r[j+1] = L.r[0];               // 插入到正确位置  
  104.      }  
  105.  }  
  106.    
  107.  /* 
  108.      打印函数. 打印当前表.  
  109.  */  
  110.  void myPrint(SqList &L)  
  111.  {  
  112.      for(int i = 1;i<MAXSIZE+1;i++)  
  113.     {  
  114.          printf("%d ",L.r[i].key);  
  115.     }  
  116.     printf("\n");  
  117.  }  
  118.    
  119.    
  120.  /***************************************main函数*************************************/  
  121.  int main()  
  122.  {  
  123.  //1. 输入20随机数   
  124.     SqList s,s1,s2,s3;  
  125.     s.length=20;  
  126.     for(int i = 1;i<MAXSIZE+1;i++)  
  127.     {  
  128.          scanf("%d",&(s.r[i].key));  
  129.     }  
  130.      s1=s2=s3=s;  
  131.  //2. 对随机数分别进行排序   
  132.      printf("快速排序--->未排序前的序列:\n");    
  133.      myPrint(s);  
  134.      QuickSort(s3,1,s3.length); //快速排序  
  135.     printf("排序后的序列:\n");  
  136.      myPrint(s3);  
  137.    
  138.      printf("选择排序--->未排序前的序列:\n");    
  139.      myPrint(s);  
  140.     SelectSort(s1);                   //选择排序  
  141.     printf("排序后的序列:\n");  
  142.     myPrint(s1);   
  143.    
  144.     printf("插入排序--->未排序前的序列:\n");    
  145.      myPrint(s);   
  146.      InsertSort(s2);                   //插入排序  
  147.      printf("排序后的序列:\n");  
  148.      myPrint(s2);   
  149.    
  150.     system("PAUSE");   
  151.     return 0;  
  152.  }   
  153.    


 (2)  算法性能比较

[cpp]  view plain  copy
  1. #include<stdio.h>  
  2.  #include<stdlib.h>  
  3.  #include <time.h>         //使用当前时钟做种子  
  4.  #define MAXSIZE 10000       //一个用作示例的顺序表的最大长度  
  5.    
  6.  /*************************************数据结构的定义*************************************/  
  7.  typedef int KeyType;         //定义关键字类型为整数类型  
  8.  typedef char InfoType;   
  9.  typedef  struct   
  10.  {  
  11.     KeyType key;              //关键字项  
  12.     InfoType otherifo;        //其他数据项  
  13.  }RedType;                    //记录类型  
  14.    
  15.  typedef struct  
  16.  {  
  17.     RedType r[MAXSIZE+1];      //r[0]闲置或用作哨兵单元  
  18.     int length;                //顺序表的长度  
  19.  }SqList;                      //顺序表类型  
  20.    
  21.    
  22.  /****************************************功能函数*****************************************/  
  23.  /* 
  24.    快速排序.  
  25.    思想:选定一个枢纽元素,对待排序序列进行分割, 
  26.    分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再 
  27.    对这两个分割好的子序列进行上述的过程。 
  28.    总结:平均效率O(nlogn),适用于排序大列表。  
  29.    此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能 
  30.    导致O(n2)的最糟用例效率。若数基本有序,效率反而最差。选项中间 
  31.    值作为枢纽,效率是O(nlogn)。基于分治法。   
  32.  */  
  33.  void QuickSort(SqList &L,int l,int h)  
  34.  {  
  35.     if (l>=h)  
  36.        return ;  
  37.     int j ,i,key;  
  38.     i=l;  
  39.     j=h;  
  40.     key=L.r[i].key;  
  41.     while(i<j)  
  42.       {  
  43.          while(i<j&&L.r[j].key>key)  
  44.             j--;  
  45.          if (i<j)  
  46.             L.r[i++].key=L.r[j].key;  
  47.          while (i<j&&L.r[i].key<key)  
  48.             i++;  
  49.          if (i<j)  
  50.             L.r[j--].key=L.r[i].key;  
  51.       }  
  52.      L.r[i].key=key;  
  53.      if (l<i-1)  
  54.          QuickSort(L,l,i-1);  
  55.      if (i+1<h)  
  56.          QuickSort(L,i+1,h);  
  57.     
  58.  }  
  59.    
  60.  /* 
  61.    选择排序。  
  62.    思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序 
  63.    放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。  
  64.  */  
  65.  void SelectSort(SqList &L)      
  66.  {  
  67.      int i,j,m,n=L.length+1 ;  
  68.      int t ;                //临时变量  
  69.      for(i=1;i<n;i++)      
  70.      {  
  71.          m=i ;  
  72.          for(j=i+1;j<n;j++)      
  73.          {  
  74.              if(L.r[j].key<L.r[m].key)  
  75.                 m=j;          
  76.          }  
  77.          if(m!=i)      
  78.          {  
  79.              t=L.r[i].key;  
  80.              L.r[i].key=L.r[m].key;  
  81.              L.r[m].key=t ;  
  82.          }  
  83.      }        
  84.  }  
  85.    
  86.  /* 
  87.    插入排序。 
  88.    思想:将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。  
  89.    最佳效率O(n);最糟效率O(n2)与冒泡、选择相同,适用于排序小列表  
  90.    若列表基本有序,则插入排序比冒泡、选择更有效率。  
  91.  */  
  92.  void InsertSort(SqList &L)  
  93.  {  
  94.    // 对顺序表L作直接插入排序。  
  95.    int i,j;  
  96.    for (i=2; i<=L.length; ++i)  
  97.      if (L.r[i].key<L.r[i-1].key)  
  98.      {  
  99.        // "<"时,需将L.r[i]插入有序子表  
  100.        L.r[0] = L.r[i];                 // 复制为哨兵  
  101.        for (j=i-1;  L.r[0].key<L.r[j].key;  --j)  
  102.          L.r[j+1] = L.r[j];             // 记录后移  
  103.        L.r[j+1] = L.r[0];               // 插入到正确位置  
  104.      }  
  105.  }  
  106.    
  107.  /* 
  108.    产生10000个随即数。  
  109.    产生1万个随机。数并进行排序。统计他所消耗的时间。  
  110.  */  
  111.  SqList random()  
  112.  {    
  113.      SqList s;  
  114.      s.length=10000;  
  115.      int i,j;  
  116.      srand((int)time(0));   
  117.      for(i=0;i<10000;i++)   
  118.      {  
  119.          j=1+(int)(1000.0*rand()/(RAND_MAX+1.0));  
  120.          s.r[i].key=j;  
  121.      }  
  122.      return s;  
  123.  }  
  124.    
  125.    
  126.  /***************************************计算时间的main函数*************************************/  
  127.  int main()  
  128.  {  
  129.      SqList s1;  
  130.      s1.length=10000;   
  131.      clock_t  start,end;  
  132.      //快速排序   
  133.      s1 = random();   
  134.      start = clock();  
  135.      QuickSort(s1,1,s1.length);  
  136.      end = clock();  
  137.      printf( "对1万个数进行快速排序的时间为%lf秒\n ", (double)(end-start)/CLOCKS_PER_SEC);   
  138.      //选择排序   
  139.      s1 = random();  
  140.      start = clock();  
  141.      SelectSort(s1);  
  142.      end = clock();  
  143.      printf("对1万个数进行选择排序的时间为%lf秒\n ", (double)(end-start)/CLOCKS_PER_SEC);   
  144.      //插入排序   
  145.      s1 = random();  
  146.      start = clock();  
  147.      InsertSort(s1);  
  148.      end = clock();  
  149.      printf("对1万个数进行插入排序的时间为%lf秒\n ", (double)(end-start)/CLOCKS_PER_SEC);   
  150.        
  151.      system("PAUSE");   
  152.     return 0;  
  153.  }   
  154.    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值