zoukankan      html  css  js  c++  java
  • sorts

    各种排序算法:

      1 #include <stdio.h>    
      2 #include <string.h>
      3 #include <ctype.h>      
      4 #include <stdlib.h>   
      5 #include <io.h>  
      6 #include <math.h>  
      7 #include <time.h>
      8 
      9 #define OK        1
     10 #define ERROR    0
     11 #define TRUE    1
     12 #define FALSE    0
     13 
     14 #define MAX_LENGTH_INSERT_SORT 7 /* 用于快速排序时判断是否选用插入排序阙值 */
     15 
     16 typedef int Status; 
     17 
     18 #define MAXSIZE 10000  /* 用于要排序数组个数最大值,可根据需要修改 */
     19 typedef struct
     20 {
     21     int r[MAXSIZE+1];    /* 用于存储要排序数组,r[0]用作哨兵或临时变量 */
     22     int length;            /* 用于记录顺序表的长度 */
     23 }SqList;
     24 
     25 /* 交换L中数组r的下标为i和j的值 */
     26 void swap(SqList *L,int i,int j) 
     27 { 
     28     int temp=L->r[i]; 
     29     L->r[i]=L->r[j]; 
     30     L->r[j]=temp; 
     31 }
     32 
     33 void print(SqList L)
     34 {
     35     int i;
     36     for(i=1;i<L.length;i++)
     37         printf("%d,",L.r[i]);
     38 
     39     printf("%d",L.r[i]);
     40     printf("
    ");
     41 }
     42 
     43 /* 对顺序表L作交换排序(冒泡排序初级版) */
     44 void BubbleSort0(SqList *L)
     45 { 
     46     for( int i=1; i<L->length; i++)
     47     {
     48         for( int j=i+1; j<=L->length; j++)
     49         {
     50             if(L->r[i]>L->r[j])
     51             {
     52                  swap(L,i,j);        /* 交换L->r[i]与L->r[j]的值 */
     53             }
     54         }
     55     }
     56 }
     57 
     58 /* 对顺序表L作冒泡排序 */
     59 void BubbleSort(SqList *L)
     60 { 
     61     for(int i=1;i<L->length;i++)
     62     {
     63         for(int j=L->length-1;j>=i;j--) /* 注意j是从后往前循环 */
     64         {
     65             if(L->r[j]>L->r[j+1])        /* 若前者大于后者(注意这里与上一算法的差异)*/
     66             {
     67                  swap(L,j,j+1);            /* 交换L->r[j]与L->r[j+1]的值 */
     68             }
     69         }
     70     }
     71 }
     72 
     73 /* 对顺序表L作改进冒泡算法 */
     74 void BubbleSort2(SqList *L)
     75 { 
     76     Status flag = TRUE;            /* flag用来作为标记 */
     77     for( int i=1; i<L->length && flag; i++) /* 若flag为true说明有过数据交换,否则停止循环 */
     78     {
     79         flag = FALSE;                /* 初始为False */
     80         for(int j=L->length-1; j>=i; j--)
     81         {
     82             if(L->r[j] > L->r[j+1])
     83             {
     84                  swap(L, j, j+1);    /* 交换L->r[j]与L->r[j+1]的值 */
     85                  flag = TRUE;        /* 如果有数据交换,则flag为true */
     86             }
     87         }
     88     }
     89 }
     90 
     91 // 双向冒泡法
     92 void Bubble_2 ( int r[], int n)
     93 {  
     94     int low = 0;   
     95     int high = n-1; //设置变量的初始值  
     96     int tmp,j;
     97 
     98     while (low < high) 
     99     {  
    100         for (j = low; j< high; ++j)    // 正向冒泡,找到最大者  
    101             if (r[j] > r[j+1]) 
    102             {  
    103                 tmp = r[j]; r[j] = r[j+1]; r[j+1] = tmp;  
    104             }   
    105         --high;            // 修改high值, 前移一位  
    106         for ( j = high; j > low; --j)    // 反向冒泡,找到最小者  
    107             if (r[j] < r[j-1]) 
    108             {  
    109                 tmp = r[j]; r[j] = r[j-1]; r[j-1] = tmp;  
    110             }  
    111         ++low;            // 修改low值,后移一位  
    112     }   
    113 } 
    114 
    115 /*
    116 多关键码排序方法:
    117 
    118 多关键码排序按照从最主位关键码到最次位关键码或从最次位到最主位关键码的顺序逐次排序,分两种方法:
    119 
    120 最高位优先(Most Significant Digit first)法,简称MSD法:
    121     1)先按k1 排序分组,将序列分成若干子序列,同一组序列的记录中,关键码k1 相等。
    122     2)再对各组按k2 排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd 对各子组排序后。
    123     3)再将各组连接起来,便得到一个有序序列。扑克牌按花色、面值排序中介绍的方法一即是MSD 法。
    124 
    125 最低位优先(Least Significant Digit first)法,简称LSD法:
    126     1) 先从kd 开始排序,再对kd-1进行排序,依次重复,直到按k1排序分组分成最小的子序列后。
    127     2) 最后将各个子序列连接起来,便可得到一个有序的序列, 扑克牌按花色、面值排序中介绍的方法二即是LSD 法。
    128 
    129 原理:
    130         按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。
    131     有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。
    132     最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
    133     基数排序基于分别排序,分别收集,所以是稳定的。
    134 @param:
    135     r: 原始数组
    136     
    137     // 原理版本
    138 void RadixSort(int r[], int length, int maxradix )  
    139 {  
    140     int k, lsp;  
    141     k = 1; 
    142     int n = 0;    // 基数内 序号
    143     int m = 1;  // 个位、十位
    144 
    145     int temp[10][length-1];  
    146     Empty( temp );    // 清空临时空间  
    147 
    148     while( k < maxradix )    // 遍历所有关键字  
    149     {  
    150         for(int i=0; i<length; i++) //分配过程  
    151         {  
    152             if(r[i] < m)  
    153                 temp[0][n] = r[i];  
    154             else  
    155                 lsp = (r[i]/m) % 10; //确定关键字  
    156 
    157             temp[lsp][n] = r[i];  
    158             n++;  
    159         } 
    160 
    161         CollectElement(r, temp); // 收集  
    162         n = 0;  
    163         m = m*10;  
    164         k++;  
    165     }  
    166 } 
    167  */
    168     // 得到最大位数
    169 int maxbit(int data[], int n)
    170 {
    171     int nBit = 1;
    172     for(int i=0; i<n; i++)
    173     {
    174         int tempC = 1;
    175         int p = data[i];
    176         while( p/10 )
    177         {
    178             p = p/10;
    179             tempC++;
    180         }
    181         if( tempC > nBit )
    182             nBit = tempC;
    183     }
    184     return nBit;
    185 }
    186 
    187 void RadixSort(int data[], int n)
    188 {  
    189     int* tmp = new int[n];
    190     int count[10];    // 每一桶中的个数
    191     int nBit = maxbit(data,n);
    192     int r=1;
    193 
    194     for(int i=0; i<nBit; i++)
    195     {
    196             // 装桶之前要先清桶
    197         for(int i=0;i<10;i++)
    198             count[i]=0;
    199 
    200         for(i=0;i<n;i++)    // 记录每个桶的个数
    201         {
    202             int k=data[i]/r;
    203             int q=k%10;
    204             count[q]++;
    205         }
    206         for(i=1; i<10; i++)    // 计算位置
    207         {
    208             count[i] += count[i-1];
    209         }
    210         for(int j=n-1; j>=0; j--)
    211         {
    212             int p = data[j]/r;
    213             int s = p%10;
    214             tmp[count[s]-1] = data[j];
    215             count[s]--;                
    216         }
    217         for(i=0; i<n; i++)
    218         {
    219             data[i] = tmp[i];        
    220         }            
    221         r = r*10;    // 更高一位
    222 
    223     }
    224 
    225 }
    226 
    227 
    228 // 计数排序
    229 void CountSort(int* pData, int n)
    230 {
    231     int* pCout = NULL;            // 记数的指针
    232     int* pSort = NULL;            // 暂存排序结果的指针
    233     pCout = (int*)malloc(sizeof(int) * n);    // 申请空间
    234     pSort = (int*)malloc(sizeof(int) * n);   
    235 
    236 
    237         // 初始化记数为0
    238     for (int i = 0; i < n; ++i)
    239     {
    240         pCout[i] = 0;
    241     }
    242         // 统计相同元素的个数
    243     for (int i = 0; i < n; ++i)
    244     {
    245         ++pCout[pData[i]];       
    246     }
    247         // pCout[i]中是 <= i 的元素个数
    248     for (int i = 1; i < n; ++i)
    249     {
    250         pCout[i] += pCout[i-1];    
    251     }
    252     for (int i = 0; i < n; ++i)
    253     {
    254         pSort[pCout[pData[i]]] = pData[i];    // 把每一个元素放在数组中相应的位置;因为pCout[pData[i]]的值就是不比他大数据的个数;      
    255         pCout[pData[i]]--;                    // 如果有相同数据的元素先减1
    256     }
    257         // 排序结束,复制到原来数组中
    258     for (int i = 0; i < n; ++i)
    259     {
    260         pData[i] = pSort[i];
    261     }
    262         // 释放申请的空间
    263     free(pCout);
    264     free(pSort);
    265 }
    266 
    267 /* 对顺序表L作简单选择排序 */
    268 void SelectSort(SqList *L)
    269 {
    270     int min;
    271     for( int i=1; i<L->length; i++)
    272     { 
    273         min = i;                        /* 将当前下标定义为最小值下标 */
    274         for ( int j = i+1;j<=L->length;j++)/* 循环之后的数据 */
    275         {
    276             if (L->r[min] > L->r[j])    /* 如果有小于当前最小值的关键字 */
    277                 min = j;                /* 将此关键字的下标赋值给min */
    278         }
    279         if(i != min)                    /* 若min不等于i,说明找到最小值,交换 */
    280             swap(L, i, min);            /* 交换L->r[i]与L->r[min]的值 */
    281     }
    282 }
    283 
    284 // 简单选择排序的改进   二元选择排序
    285 void SelectSort(int r[],int n) 
    286 {  
    287     int i, j, min, max, tmp;  
    288     for (i = 1; i <= n/2; i++) 
    289     {    
    290             // 做不超过n/2趟选择排序   
    291         min = i; max = i ;    // 分别记录最大和最小关键字记录位置  
    292         for (j = i+1; j <= n-i; j++) 
    293         {  
    294             if (r[j] > r[max]) 
    295             {   
    296                 max = j; 
    297                 continue;   
    298             }    
    299             if (r[j] < r[min]) 
    300             {   
    301                 min = j;   
    302             }     
    303         }    
    304 
    305         tmp = r[i-1]; r[i-1] = r[min]; r[min] = tmp;  // swap(a, min, i-1);
    306         tmp = r[n-i]; r[n-i] = r[max]; r[max] = tmp;  // swap(a, max, n-i)
    307     }   
    308 } 
    309 
    310 /* 对顺序表L作直接插入排序 
    311 
    312 插入排序(insert sorting)思想:
    313 当插入第i个元素时,前面的v[0],v[1],v[2]......v[i-1],已经排好序了.
    314 这时用v[i]的插入码与 v[i-1],v[i-2],......排序码进行比较,
    315 找到插入的位置即插入v[i],原来位置上的元素从后向前依次后移。
    316 
    317 时间复杂度:  平均比较次数O(n2),平均移动次数 O(n2).
    318 直接插入排序是一种稳定的排序。元素大部分有序时 效率会更高,这时比较次数和移动次数都会减少。
    319 
    320 */
    321 void InsertSort(SqList *L)
    322 { 
    323     int j;
    324     for( int i=2; i<=L->length; i++)
    325     {
    326         if (L->r[i] < L->r[i-1])        /* 需将L->r[i]插入有序子表 */
    327         {
    328             L->r[0] = L->r[i];            /* 设置哨兵 */
    329             for( j=i-1; L->r[j] > L->r[0]; j--)
    330                 L->r[j+1] = L->r[j];    /* 记录后移 */
    331 
    332             L->r[j+1] = L->r[0];        /* 插入到正确位置 */
    333         }
    334     }
    335 }
    336 
    337 /* 对顺序表L作希尔排序 
    338 
    339 希尔排序(Shell sort)基本思想: 改进的直接插入算法。
    340 设待排序的元素序列有n个元素,首先取一整数gap(<n)作为间隔,将全部元素分为gap个子序列,
    341 所有距离为gap的元素 放在同一序列中,在每个子序列中分别进行直接插入排序。
    342 然后缩小gap,例如gap = gap/2,重复上述的子序列划分与排序工作。
    343 开始由于gap取值大,每个子序列元素少,排序速度快,待排序后期,
    344 gap值逐渐变小,子序列元素变多,但由于前面的工作基础,大多数元素已经有序,所以排序速度快。
    345 
    346 
    347 希尔排序是一种不稳定的排序
    348 */
    349 void ShellSort(SqList *L)
    350 {
    351     int j, k = 0;
    352     int d = L->length;
    353     do
    354     {
    355         d = d/3 + 1;                /* 增量序列 */
    356         for(int i=d+1; i<=L->length; i++)
    357         {
    358             if (L->r[i] < L->r[i-d])    /*  需将L->r[i]插入有序增量子表 */ 
    359             { 
    360                 L->r[0] = L->r[i];        /*  暂存在L->r[0] */
    361                 for( j = i-d; j>0 && L->r[0]<L->r[j]; j -= d)
    362                     L->r[j+d]=L->r[j];    /*  记录后移,查找插入位置 */
    363 
    364                 L->r[j+d]=L->r[0];        /*  插入 */
    365             }
    366         }
    367         printf("第%d趟排序结果: ",++k);
    368         print(*L);
    369     }
    370     while( d > 1 );
    371 
    372 }
    373 
    374 
    375 /*  
    376 大根堆排序的基本思想: 
    377 1) 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区; 
    378 2) 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,
    379     由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key; 
    380 3) 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。 
    381     然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,
    382     由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系 R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
    383 */
    384 
    385 /*
    386  @brief:
    387      已知L->r[s..len]中记录的关键字除L->r[s]之外均满足堆的定义,
    388      本函数调整L->r[s]的关键字,使L->r[s..len]成为一个大顶堆
    389  @param:
    390     cur: 当前位置 s
    391     len: 当前状态的最大值
    392 
    393 m:当前堆的大小
    394  */
    395 void HeapAdjust(SqList *L, int cur, int len)
    396 { 
    397     int temp = L->r[cur];
    398     for(int j = 2*cur; j <= len; j *= 2)// 沿关键字较大的孩子结点向下筛选(大根堆)
    399     {
    400         if(j < len && L->r[j] < L->r[j+1])
    401             ++j;                        // j为关键字中较大的记录的下标
    402         if(temp >= L->r[j])
    403             break;                        /* 应插入在位置 cur 上 */
    404 
    405         L->r[cur] = L->r[j];
    406         cur = j;
    407     }
    408     L->r[cur] = temp;                    /* 插入 */
    409 }
    410 
    411 /*  对顺序表L进行堆排序 */
    412 void HeapSort( SqList* L )
    413 {
    414     for( int i = L->length/2; i>0; i--)    /*  把L中的r构建成一个大根堆 */
    415          HeapAdjust(L, i, L->length);
    416 
    417     for( int i = L->length; i>1; i--)
    418     { 
    419          swap(L, 1, i);                /* 将堆顶记录和当前未经排序子序列的最后一个记录交换 */
    420          HeapAdjust(L, 1, i-1);        /* 将L->r[1..i-1]重新调整为大根堆 */
    421     }
    422 }
    423 
    424 
    425 #if 0
    426 
    427 
    428 #include <iostream>
    429 #include <algorithm>
    430 
    431 using std::cout;
    432 using std::cin;
    433 using std::endl;
    434 
    435 template<class T>
    436 class Out
    437 {
    438 public:
    439     void operator()(T o)
    440     {
    441         cout<<o<<'	';
    442     }
    443 };
    444 template<class T>
    445 void Swap(T& a,T&b)
    446 {
    447     if(a == b)
    448         return;
    449     T t=a;
    450     a=b;
    451     b=t;
    452 }
    453 inline int Rt(int idx)
    454 {
    455     return (idx<<1)+2;
    456 }
    457 inline int Lt(int idx)
    458 {
    459     return (idx<<1)+1;
    460 }
    461 
    462 template<class T>
    463 void HeapBuild(T* A,int idx,int size)
    464 {
    465     int child;
    466     for(; idx<=size/2; idx=child)
    467     {
    468         child=Lt(idx);
    469         if (child<size&&A[child]>A[idx])
    470         {
    471             Swap(A[idx],A[child]);
    472         }
    473         child=Rt(idx);
    474         if (child<size&&A[child]>A[idx])
    475         {
    476             Swap(A[idx],A[child]);
    477         }
    478     }
    479 }
    480 template<class T>
    481 void HeapSort(T* A, int size)
    482 {
    483     if(size == 1)
    484         return;
    485 
    486     for (int i=size/2; i>=0; i--)
    487     {
    488         HeapBuild(A,i,size);
    489     }
    490     int i=size-1;
    491     cout<<"swap max number:"<<A[0]<<","<<A[i]<<endl;
    492     Swap(A[0],A[i]);
    493     //现在得到了一个最大值,对前size-1个递归调用HeapSort
    494     HeapSort(A, i);
    495 }
    496 
    497 int main()
    498 {
    499     int size=0;
    500     cout<<"enter elements count num:"<<endl;
    501     cin>>size;
    502     //    size = 10;
    503     int* elems = new int[size];
    504     //    int elems[] = {1, 8, 4, 5, 6, 7, 11, 2, 3, 45};
    505     cout<<"Input all elements to be sorted:"<<endl;
    506     for(int i=0; i<size; cin>>elems[i++]);
    507 
    508     HeapSort(elems,size);
    509     std::for_each(elems,elems+size,Out<int>());
    510     delete []elems;
    511 
    512     system("pause");
    513     return 0;
    514 
    515 }
    516 
    517 #endif
    518 
    519 #pragma region MergeSort
    520 /*  
    521 归并算法思想:
    522     分而治之(divide - conquer);每个递归过程涉及三个步骤
    523     1) 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.
    524     2) 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作
    525     3) 合并: 合并两个排好序的子序列,生成排序结果. 
    526 */
    527 
    528 /* 将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n] */
    529 void Merge(int SR[],int TR[], int start, int mid, int end)
    530 {
    531     int j,k,l;
    532     for(j=mid+1,k=start; start<=mid && j<=end; k++)    /* 将SR中记录由小到大地并入TR */
    533     {
    534         if (SR[start] < SR[j])
    535             TR[k] = SR[start++];
    536         else
    537             TR[k] = SR[j++];
    538     }
    539     if(start<=mid)
    540     {
    541         for(l=0; l<=mid-start; l++)
    542             TR[k+l] = SR[start+l];        /* 将剩余的SR[i..m]复制到TR */
    543     }
    544     if(j<=end)
    545     {
    546         for(l=0; l<=end-j; l++)
    547             TR[k+l] = SR[j+l];            /* 将剩余的SR[j..n]复制到TR */
    548     }
    549 }
    550 
    551 /* 递归法 */
    552 /* 将SR[s..t]归并排序为TR1[s..t] */
    553 void MSort(int SR[],int TR1[], int start, int end)
    554 {
    555     int mid;
    556     int TR2[MAXSIZE+1];
    557 
    558     if(start == end)
    559     {
    560         TR1[start] = SR[start];
    561     }
    562     else
    563     {
    564         mid = (start + end)/2;        /* 将SR[s..t]平分为SR[s..m]和SR[m+1..t] */
    565         MSort(SR,TR2, start, mid);    /* 递归地将SR[s..m]归并为有序的TR2[s..m] */
    566         MSort(SR,TR2, mid+1, end);    /* 递归地将SR[m+1..t]归并为有序的TR2[m+1..t] */
    567 
    568         Merge(TR2,TR1, start, mid, end);    /* 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t] */
    569     }
    570 }
    571 
    572 /* 对顺序表L作归并排序 */
    573 void MergeSort(SqList *L)
    574 { 
    575     MSort(L->r, L->r, 1, L->length);
    576 }
    577 
    578 
    579 /* 非递归法 */
    580 /* 
    581 @brief:
    582     将SR[]中相邻长度为s的子序列两两归并到TR[] 
    583 @param:
    584     size: 归并相邻字段的大小
    585      len: 原始数据的总长度
    586 */
    587 void MergePass(int SR[],int TR[], int size,int len)
    588 {
    589     int i = 1;
    590 
    591     while(i <= len-2*size+1)
    592     {            
    593         Merge(SR,TR, i, i+size-1, i+2*size-1);    // 两两归并(归并长度为 size 的两个相邻子序列)
    594         i += 2*size;        
    595     }
    596 
    597     if(i < len-size+1)                // 归并最后两个序列(尚有两个子序列,其中后一个长度小于len)
    598     {
    599         Merge(SR,TR, i, i+size-1, len);
    600     }
    601     else                            // 若最后只剩下单个子序列
    602     {
    603         for( int j = i; j <= len; j++)
    604             TR[j] = SR[j];
    605     }
    606 }
    607 
    608 /* 对顺序表L作归并非递归排序 */
    609 void MergeSort2(SqList *L)
    610 {
    611     int* TR = (int*)malloc( L->length * sizeof(int) );    /* 申请额外空间 */
    612 
    613     int _size = 1;
    614     while( _size < L->length )
    615     {
    616         MergePass(L->r, TR, _size, L->length);
    617         _size *= 2;        /* 子序列长度加倍 */
    618 
    619         MergePass(TR, L->r, _size, L->length);
    620         _size *= 2;        /* 子序列长度加倍 */
    621     }
    622 }
    623 
    624 /*
    625 (归并)算法分析
    626 
    627 1、稳定性
    628     归并排序是一种稳定的排序。
    629 
    630 2、存储结构要求
    631     可用顺序存储结构,也易于在链表上实现。
    632 
    633 3、时间复杂度
    634     对长度为n的文件,需进行log(n)趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
    635 
    636 4、空间复杂度
    637     需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。
    638 */
    639 
    640 #pragma endregion MergeSort
    641 
    642 #pragma region QuickSort
    643 /* 交换顺序表L中子表的记录,使枢轴记录到位,并返回其所在位置 */
    644 /* 此时在它之前(后)的记录均不大(小)于它。 */
    645 int Partition(SqList *L,int low,int high)
    646 { 
    647     int pivotkey;
    648 
    649     pivotkey = L->r[low]; /* 用子表的第一个记录作枢轴记录 */
    650     while(low < high)          /* 从表的两端交替地向中间扫描 */
    651     { 
    652         while(low<high && L->r[high]>=pivotkey)
    653             high--;
    654         swap(L,low,high);/* 将比枢轴记录小的记录交换到低端 */
    655         while(low<high && L->r[low]<=pivotkey)
    656             low++;
    657         swap(L,low,high);/* 将比枢轴记录大的记录交换到高端 */
    658     }
    659     return low; /* 返回枢轴所在位置 */
    660 }
    661 
    662 /* 对顺序表L中的子序列L->r[low..high]作快速排序 */
    663 void QSort(SqList *L,int low,int high)
    664 { 
    665     int pivot;
    666     if(low < high)
    667     {
    668         pivot = Partition(L,low,high);    /*  将L->r[low..high]一分为二,算出枢轴值pivot */
    669         QSort(L, low, pivot-1);            /*  对低子表递归排序 */
    670         QSort(L, pivot+1, high);        /*  对高子表递归排序 */
    671     }
    672 }
    673 
    674 /* 对顺序表L作快速排序 */
    675 void QuickSort(SqList *L)
    676 { 
    677     QSort(L, 1, L->length);
    678 }
    679 
    680 
    681 /* 改进后快速排序******************************** */
    682 
    683 /* 快速排序优化算法 */
    684 int Partition1(SqList *L,int low,int high)
    685 { 
    686     int pivotkey;
    687 
    688     int m = low + (high - low) / 2; /* 计算数组中间的元素的下标 */  
    689     if (L->r[low]>L->r[high])            
    690         swap(L,low,high);    /* 交换左端与右端数据,保证左端较小 */
    691     if (L->r[m]>L->r[high])
    692         swap(L,high,m);        /* 交换中间与右端数据,保证中间较小 */
    693     if (L->r[m]>L->r[low])
    694         swap(L,m,low);        /* 交换中间与左端数据,保证左端较小 */
    695 
    696     pivotkey = L->r[low]; /* 用子表的第一个记录作枢轴记录 */
    697     L->r[0]  = pivotkey;    /* 将枢轴关键字备份到L->r[0] */
    698     while(low<high) /*  从表的两端交替地向中间扫描 */
    699     { 
    700         while(low<high&&L->r[high]>=pivotkey)
    701             high--;
    702         L->r[low]=L->r[high];
    703         while(low<high&&L->r[low]<=pivotkey)
    704             low++;
    705         L->r[high]=L->r[low];
    706     }
    707     L->r[low]=L->r[0];
    708     return low;        /* 返回枢轴所在位置 */
    709 }
    710 
    711 void QSort1(SqList *L,int low,int high)
    712 { 
    713     int pivot;
    714     if( (high-low) > MAX_LENGTH_INSERT_SORT )
    715     {
    716         while(low < high)
    717         {
    718             pivot = Partition1(L, low, high); /*  将L->r[low..high]一分为二,算出枢轴值pivot */
    719             QSort1(L,low,pivot-1);        /*  对低子表递归排序 */
    720             QSort1(L,pivot+1,high);        /*  对高子表递归排序 */
    721             low=pivot+1;    /* 尾递归 */
    722         }
    723     }
    724     else
    725         InsertSort(L);
    726 }
    727 
    728 /* 对顺序表L作快速排序 */
    729 void QuickSort1(SqList *L)
    730 { 
    731     QSort1(L, 1, L->length);
    732 }
    733 
    734 #pragma endregion QuickSort
    735 
    736 
    737 
    738 #define N 9
    739 int main()
    740 {
    741    int i;
    742    
    743    /* int d[N]={9,1,5,8,3,7,4,6,2}; */
    744    int d[N]={50,10,90,30,70,40,80,60,20};
    745    /* int d[N]={9,8,7,6,5,4,3,2,1}; */
    746 
    747    SqList l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10;
    748    
    749    for(i=0;i<N;i++)
    750      l0.r[i+1] = d[i];
    751    l0.length = N;
    752 
    753    l1=l2=l3=l4=l5=l6=l7=l8=l9=l10=l0;
    754 
    755    printf("排序前:
    ");
    756    print(l0);
    757 
    758    printf("初级冒泡排序:
    ");
    759    BubbleSort0(&l0);
    760    print(l0);
    761    
    762    printf("冒泡排序:
    ");
    763    BubbleSort(&l1);
    764    print(l1);
    765    
    766    printf("改进冒泡排序:
    ");
    767    BubbleSort2(&l2);
    768    print(l2);
    769    
    770    printf("选择排序:
    ");
    771    SelectSort(&l3);
    772    print(l3);
    773    
    774    printf("直接插入排序:
    ");
    775    InsertSort(&l4);
    776    print(l4);
    777 
    778    printf("希尔排序:
    ");
    779    ShellSort(&l5);
    780    print(l5);
    781     
    782    printf("堆排序:
    ");
    783    HeapSort(&l6);
    784    print(l6);
    785 
    786    printf("归并排序(递归):
    ");
    787    MergeSort(&l7);
    788    print(l7);
    789 
    790    printf("归并排序(非递归):
    ");
    791    MergeSort2(&l8);
    792    print(l8);
    793 
    794    printf("快速排序:
    ");
    795    QuickSort(&l9);
    796    print(l9);
    797 
    798    printf("改进快速排序:
    ");
    799    QuickSort1(&l10);
    800    print(l10);
    801 
    802 
    803 /*大数据排序*/
    804 /* 
    805     srand(time(0));  
    806     int Max=10000;
    807     int d[10000];
    808     int i;
    809     SqList l0;
    810     for(i=0;i<Max;i++)
    811         d[i]=rand()%Max+1;
    812     for(i=0;i<Max;i++)
    813         l0.r[i+1]=d[i];
    814     l0.length=Max;
    815     MergeSort(l0);
    816     print(l0);
    817 */
    818 
    819     system("pause");
    820     return 0;
    821 }
  • 相关阅读:
    系统并发报too much open files 错误
    plsql 安装Some Oracle Net versions cannot connect from a path with parentheses
    mysql登录报错
    web.xml配置文件详解之一servlet配置
    hibernate createQuery查询传递参数的两种方式
    mysql登录连接远程数据库命令行
    java 项目打包部署 过程
    flex ArrayCollection的新增与删除的同步
    加大eclipse以及jvm的内存
    2017 八月 UFED Series Releases 系列 6.3 重大更新发布
  • 原文地址:https://www.cnblogs.com/uestc999/p/3946769.html
Copyright © 2011-2022 走看看