各种排序算法:
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("\n"); 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<<'\t'; 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("排序前:\n"); 756 print(l0); 757 758 printf("初级冒泡排序:\n"); 759 BubbleSort0(&l0); 760 print(l0); 761 762 printf("冒泡排序:\n"); 763 BubbleSort(&l1); 764 print(l1); 765 766 printf("改进冒泡排序:\n"); 767 BubbleSort2(&l2); 768 print(l2); 769 770 printf("选择排序:\n"); 771 SelectSort(&l3); 772 print(l3); 773 774 printf("直接插入排序:\n"); 775 InsertSort(&l4); 776 print(l4); 777 778 printf("希尔排序:\n"); 779 ShellSort(&l5); 780 print(l5); 781 782 printf("堆排序:\n"); 783 HeapSort(&l6); 784 print(l6); 785 786 printf("归并排序(递归):\n"); 787 MergeSort(&l7); 788 print(l7); 789 790 printf("归并排序(非递归):\n"); 791 MergeSort2(&l8); 792 print(l8); 793 794 printf("快速排序:\n"); 795 QuickSort(&l9); 796 print(l9); 797 798 printf("改进快速排序:\n"); 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 }