常用的排序算法

来源:互联网 发布:如何发布php网站 编辑:程序博客网 时间:2024/05/26 05:53
  1. //常用的排序算法  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. typedef int ElemType;  
  6.   
  7. /* 
  8. 1、插入排序 
  9. (1)直接插入排序算法 
  10. 算法思想:将等排序列划分为有序与无序两部分,然后再依次将无序部分插入到已经有序的部分,最后 

  11. 就可以形成有序序列。 
  12. 操作步骤如下: 
  13. 1)查找出元素L(i)在表中的插入位置K; 
  14. 2)将表中的第K个元素之前的元素依次后移一个位置; 
  15. 3)将L(i)复制到L(K)。 

  16. 时间复杂度为:O(n^2) 
  17. */  
  18. void InsertSort(ElemType arr[], int length)  
  19. {  
  20.     int i, j;  
  21.     ElemType guard; // 哨兵  
  22.   
  23.     for (i = 1; i < length; ++i)  
  24.     {  
  25.         if (arr[i] < arr[i-1]) // 在无序部分寻找一个元素,使之插入到有序部分后仍然有序  
  26.         {  
  27.             guard = arr[i];// 复制到“哨兵”  
  28.           
  29.             // 将第i个元素之前的元素依次后移一个位置  
  30.             for (j = i - 1; arr[j] > guard; j--)  
  31.             {  
  32.                 arr[j + 1] = arr[j];  
  33.             }  
  34.   
  35.             arr[j + 1] = guard; // 复制到插入位置  
  36.         }  
  37.     }  
  38. }  
  39.   
  40.   
  41. /* 
  42.   2、折半插入排序 
  43.   使用于排序表为顺序存储的线性表 
  44.   在查找插入位置时,采用折半查找 
  45.   算法思想是: 
  46.   1)设置折半查找范围; 
  47.   2)折半查找 
  48.   3)移动元素 
  49.   4)插入元素 
  50.   5)继续操作1)、2)、3)、4)步,直到表成有序。 
  51. */  
  52. void BinaryInsertSort(ElemType arr[], int length)  
  53. {  
  54.     int i, j, low, high, mid;  
  55.     ElemType tmp;  
  56.   
  57.     for ( i = 1; i < length; ++i )  
  58.     {  
  59.         tmp = arr[i]; // 复制到哨兵  
  60.           
  61.         // 设置折半查找范围  
  62.         low = 0;        
  63.         high = i;  
  64.   
  65.         while (low <= high) // 折半查找  
  66.         {  
  67.             mid = (low + high) / 2;  
  68.   
  69.             if (arr[mid] > tmp) // 在左半部分查找  
  70.             {  
  71.                 high = mid - 1;  
  72.             }  
  73.             else  
  74.             {  
  75.                 low = mid + 1; // 在右半部分查找  
  76.             }  
  77.         }  
  78.   
  79.         // 移动元素  
  80.         for ( j = i - 1; j >= high + 1; --j )  
  81.         {  
  82.             arr[j + 1] = arr[j];  
  83.         }  
  84.   
  85.         arr[j + 1] = tmp;  
  86.     }  
  87. }  
  88.   
  89.   
  90. /* 
  91. 3、希尔(Shell)排序 
  92.    基本思想: 
  93.    先将待排序的表分割成若干个形若L[i, i+d, i+2d, ..., i+kd]的“特殊”子表,分别进行直接插入排序, 
  94.    当整个表已呈“基本有序”时,再对全体记录进行一次直接插入排序。 
  95.    算法过程: 
  96.    1)先取一个小于n的步长d1,把表中全部记录分成d1个组,所有距离为d1的倍数的记录放在同一组中,在各 
  97.       组中进行直接插入排序; 
  98.    2)然后取第二个步长d2 < d1, 重复步骤1 
  99.    3)直到dk = 1,再进行最后一次直接插入排序 
  100. */  
  101.   
  102. void ShellSort(ElemType arr[], int length)  
  103. {  
  104.     int i, j, dk = length / 2;  
  105.     ElemType tmp;  
  106.   
  107.     while (dk >= 1)// 控制步长  
  108.     {  
  109.         for (i = dk; i < length; ++i)  
  110.         {  
  111.             if (arr[i] < arr[i - dk])  
  112.             {  
  113.                 tmp = arr[i]; // 暂存  
  114.   
  115.                 // 后移  
  116.                 for (j = i - dk; j >= 0 && tmp < arr[j]; j -= dk)  
  117.                 {  
  118.                     arr[j + dk] = arr[j];  
  119.                 }  
  120.   
  121.                 arr[j + dk] = tmp;  
  122.             }  
  123.         }  
  124.   
  125.         dk /= 2;  
  126.     }  
  127. }  
  128.   
  129.   
  130. /* 
  131. 4、冒泡排序算法 
  132.    基本思想: 
  133.    假设待排序的表长为n, 从后向前或从前向后两两比较相邻元素的值,若为逆序,则交换之,直到序列比较完。 
  134.    这样一回就称为一趟冒泡。这样值较大的元素往下“沉”,而值较小的元素入上“浮”。 
  135.    时间复杂度为O(n^2) 
  136. */  
  137. void BubbleSort(ElemType arr[], int length)  
  138. {  
  139.     int i, j;  
  140.     ElemType tmp;  
  141.   
  142.     for (i = 0; i < length - 1; ++i)// 趟次  
  143.     {  
  144.         for (j = i + 1; j < length; ++j)  
  145.         {  
  146.             if (arr[i] > arr[j])  
  147.             {  
  148.                 tmp = arr[i];  
  149.                 arr[i] = arr[j];  
  150.                 arr[j] = tmp;  
  151.             }  
  152.         }  
  153.     }  
  154. }  
  155.   
  156.   
  157. /* 
  158. 5、快速排序算法 
  159.    基本思想:基于分治法,在待排序的n个元素中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的 
  160.    两部分L[1..k-1]和L[k+1 .. n],使得第一部分中的所有元素值都小于pivot,而第二部分中的所有元素值都大于pivot, 
  161.    则基准元素放在了其最终位置L(K)上,这个过程为一趟快速排序。而后分别递归地对两个子表重复上述过程,直到每 
  162.    部分内只有一个元素或为空为止,即所有元素都放在了其最终位置上。 
  163. */  
  164.   
  165. int Partition(ElemType arr[], int left, int right)  
  166. {  
  167.     ElemType pivot = arr[left]; // 以当前表中第一个元素为枢轴值  
  168.   
  169.     while (left < right)  
  170.     {  
  171.         // 从右向左找一个比枢轴值小的元素的位置  
  172.         while (left < right && arr[right] >= pivot)   
  173.         {  
  174.             --right;  
  175.         }  
  176.   
  177.         arr[left] = arr[right]; // 将比枢轴值小的元素移动到左端  
  178.   
  179.         // 从左向右查找比枢轴值大的元素的位置  
  180.         while (left < right && arr[left] <= pivot)  
  181.         {  
  182.             ++left;   
  183.         }  
  184.   
  185.         arr[right] = arr[left];// 将比枢轴值大的元素移动到右端  
  186.     }  
  187.   
  188.     arr[left] = pivot; // 将枢轴元素放在最终位置  
  189.   
  190.     return left;  
  191. }  
  192.   
  193. void QuickSort(ElemType arr[], int left, int right)  
  194. {  
  195.     if (left < right)  
  196.     {  
  197.         int pivotPos = Partition(arr, left, right); // 划分  
  198.         QuickSort(arr, left, pivotPos - 1); // 快速排序左半部分  
  199.         QuickSort(arr, pivotPos + 1, right); // 快速排序右半部分  
  200.     }  
  201. }  
  202.   
  203.   
  204. /* 
  205. 6、简单选择排序算法 
  206.    基本思想: 
  207.    假设排序表为L[1...n],第i趟排序从表中选择关键字最小的元素与Li交换,第一趟排序可以确定一个元素的 
  208.    最终位置,这样经过n-1趟排序就可以使得整个排序表有序。 
  209. */  
  210.   
  211. void SelectSort(ElemType arr[], int length)  
  212. {  
  213.     int i, j, min;  
  214.     ElemType tmp;  
  215.   
  216.     for (i = 0; i < length - 1; ++i) // 需要n-1趟  
  217.     {  
  218.         min = i;  
  219.   
  220.         for (j = i + 1; j < length; ++j)  
  221.         {  
  222.             if (arr[j] < arr[min]) // 每一趟选择元素值最小的下标  
  223.             {  
  224.                 min = j;  
  225.             }  
  226.         }  
  227.   
  228.         if (min != i) // 如果第i趟的Li元素值该趟找到的最小元素值,则交换,以使Li值最小  
  229.         {  
  230.             tmp = arr[i];  
  231.             arr[i] = arr[min];  
  232.             arr[min] = tmp;  
  233.         }  
  234.     }  
  235. }  
  236.   
  237. /* 
  238. 7、堆排序算法 
  239.     堆的定义如下:n个关键字序列号L[1..n]称为堆,仅当该序列满足: 
  240.     1)L(i) <= L(2i)且L(i) <= L(2i+1) 或 2)L(i) >= L(2i)且L(i) >= L(2i+1) 
  241.     满足第一种情况的堆,称为小根堆(小顶堆); 
  242.     满足第二种情况的堆,称为大根堆(大顶堆)。 
  243. */  
  244. void HeapAdjust(ElemType *a,int i,int size)  //调整堆   
  245. {  
  246.     int lchild = 2 * i;       //i的左孩子节点序号   
  247.     int rchild = 2 * i + 1;     //i的右孩子节点序号   
  248.     int max = i;            //临时变量   
  249.   
  250.     if(i <= size / 2)          //如果i是叶节点就不用进行调整   
  251.     {  
  252.         if (lchild <= size && a[lchild] > a[max])  
  253.         {  
  254.             max = lchild; // 左孩子比双亲值还大,需要调整  
  255.         }    
  256.   
  257.         if (rchild <= size && a[rchild] > a[max])  
  258.         {  
  259.             max = rchild;// 右孩子比双亲值还大,需要调整  
  260.         }  
  261.   
  262.         if (max != i) // 需要调整  
  263.         {  
  264.             ElemType tmp = a[max];  
  265.             a[max] = a[i];  
  266.             a[i] = tmp;  
  267.   
  268.             HeapAdjust(a, max, size);    //避免调整之后以max为父节点的子树不是堆   
  269.         }  
  270.     }          
  271. }  
  272.   
  273. void BuildHeap(ElemType *a,int size)    //建立堆   
  274. {  
  275.     for (int i = size / 2; i >= 0; i--)    //非叶节点最大序号值为size/2   
  276.     {  
  277.         HeapAdjust(a, i, size);      
  278.     }      
  279. }   
  280.   
  281. void HeapSort(ElemType *a, int size)    //堆排序   
  282. {  
  283.     BuildHeap(a,size);  
  284.   
  285.     for(int i = size - 1; i >= 0; i--)  
  286.     {  
  287.         swap(a[0], a[i]);           //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面   
  288.         BuildHeap(a, i-1);        //将余下元素重新建立为大顶堆   
  289.         HeapAdjust(a,1,i-1);      //重新调整堆顶节点成为大顶堆  
  290.     }  
  291. }   
  292.   
  293.   
  294.   
  295.   
  296.   
  297.   
  298. void Display(ElemType arr[], int length)  
  299. {  
  300.     for ( int i = 0; i < length; ++i )  
  301.     {  
  302.         cout << arr[i] << " ";  
  303.     }  
  304.   
  305.     cout << endl;  
  306. }  
  307. int main()  
  308. {  
  309.     ElemType arr[] = {2, 1, 5, 3, 4, 0, 6, 9, -1, 4, 12};  
  310.   
  311.     //InsertSort(arr, sizeof(arr) / sizeof(ElemType));  
  312.     //BinaryInsertSort(arr, sizeof(arr) / sizeof(ElemType));  
  313.     //ShellSort(arr, sizeof(arr) / sizeof(ElemType));  
  314.     //BubbleSort(arr, sizeof(arr) / sizeof(ElemType));  
  315.     //QuickSort(arr, 0,  sizeof(arr) / sizeof(ElemType) - 1);  
  316.     HeapSort(arr, sizeof(arr) / sizeof(ElemType));  
  317.     Display(arr, sizeof(arr) / sizeof(ElemType));  
  318.   
  319.     return 0;  
  320. }  
0 0
原创粉丝点击