数据结构之排序

来源:互联网 发布:主流建站软件 编辑:程序博客网 时间:2024/06/14 21:26

1、这篇文章中,涉及到的排序算法有:冒泡、选择、堆排序、快排。

2、算法原理概述

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /// --------------       冒泡排序         ----------------  
  2. /* 冒泡排序 
  3.   
  4.  算法原理: 
  5.  1、比较相邻的两个元素,若第一个比第二个大,就交换他们两个 
  6.  2、从第一个到结尾的最后一对,对每一对相邻元素做同样的操作。最后的元素应该是最大的数 
  7.  3、除了最后一个,针对所有的元素重复以上的步骤 
  8.  4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较 
  9.  5、注意:冒泡排序,默认每次都是找的最大或者最小的值,每一轮比较完毕,最后的元素一定是最大或最小的值 
  10.  */  
  11.   
  12. /// 帧数或浮点数皆可使用  
  13. template <typename T>  
  14. void bubble_sort(T *array, int length)  
  15. {  
  16.     /// 计数器  
  17.     int i = 0, j =0;  
  18.       
  19.     ///  
  20.     for (; i < length - 1; i++)  
  21.     {  
  22.         for (j = 0; j < length - 1 - i; j++)  
  23.         {  
  24.             if (array[j] > array[j+1])  
  25.             {  
  26.                 array[j+1] = array[j] ^ array[j+1];  
  27.                 array[j] = array[j] ^ array[j+1];  
  28.                 array[j+1] = array[j] ^ array[j+1];  
  29.             }  
  30.         }  
  31.     }  
  32. }  
  33. /// --------------       冒泡排序         ----------------  
  34.   
  35.   
  36. /// --------------       选择排序         ----------------  
  37. /* 
  38.     原理:每一次从待排序的数据元素中选择出最小的或者最大的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 
  39.     选择排序的第一层循环从开始元素到倒数第二个元素,主要是在每次进入第二层的循环之前,将外层循环下的值给临时变量,接下来的第二层循环中若发现比这个最小的位置的元素更小的元素,则将更小的下表赋给临时变量,最后,在二层循环退出后,若临时变量没有改变,则说明没有改变,有比当前外层循环更小的元素,需要将这两个元素交换 
  40.  */  
  41. template<typename T>  
  42. void selection_sort(T *array, int length)  
  43. {  
  44.     /// 计数器  
  45.     int temp = NULL;  
  46.     T array_temp;  
  47.       
  48.     for (int i= 0; i < length - 1; i++)  
  49.     {  
  50.         /// 记录位置  
  51.         temp = i;  
  52.         for (int j = i + 1; j < length; j++)  
  53.         {  
  54.             if (array[temp] > array[j])  
  55.             {  
  56.                 /// 记录大的值得位置  
  57.                 temp = j;  
  58.             }  
  59.         }  
  60.         /// 这里是二层循环结束的地方  
  61.         if (i != temp)  
  62.         {  
  63.             array_temp = array[temp];  
  64.             array[temp] = array[i];  
  65.             array[i] = array_temp;  
  66.         }  
  67.     }  
  68.       
  69. }  
  70. /// --------------       选择排序         ----------------  
  71.   
  72. /// --------------       堆排序           ----------------  
  73. /*      思想  和 基本操作 
  74.   
  75.  (1)用大根堆排序的基本思想 
  76.  ① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区 
  77.  ② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key 
  78.  ③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。直到无序区只有一个元素为止。 
  79.   
  80.  (2)大根堆排序算法的基本操作: 
  81.  ①建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2) 其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。 
  82.  ②调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,如果最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为是沿着深度方向进行调整的。 
  83.  ③堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn) 
  84.  */  
  85. ///--------整理结点  
  86. template<typename T>  
  87. void MinHeapify(T *array, int size, int element)  
  88. {  
  89.     /// 左右子树  
  90.     int lchild = element * 2 + 1;  
  91.     int rchild = lchild + 1;  
  92.       
  93.     /// 子树均在范围内  
  94.     while (rchild < size)  
  95.     {  
  96.         /// 若左右子树都小  
  97.         if (array[element] < array[lchild] && array[element] < array[rchild])  
  98.         {  
  99.             return;  
  100.         }  
  101.         /// 若左边最小  
  102.         if (array[lchild] < array[rchild])  
  103.         {  
  104.             /// 把左面的提到上面去  
  105.             swap(array[element], array[rchild]);  
  106.             /// 循环时,整理子树  
  107.             element = lchild;  
  108.         }  
  109.         /// 否则右边最小,同理  
  110.         else  
  111.         {  
  112.             swap(array[element], array[rchild]);  
  113.             element = lchild;  
  114.         }  
  115.         /// 重新计算子树的位置  
  116.         lchild = element * 2 + 1;  
  117.         /// 只有左子树且子树小于自己  
  118.         if (lchild < size && array[lchild] < array[element])  
  119.         {  
  120.             swap(array[lchild], array[element]);  
  121.         }  
  122.         return;  
  123.     }  
  124. }  
  125.   
  126. /// ----- 堆排序操作  
  127. template<typename T>  
  128. void Heap_sort(T *array, int size)  
  129. {  
  130.     /// 从子树整理树  
  131.     for (int i = size - 1; i >= 0; i--)  
  132.     {  
  133.         MinHeapify(array, size, i);  
  134.     }  
  135.     /// 拆除树  
  136.     while (size > 0)  
  137.     {  
  138.         /// 将根与数组最末交换  
  139.         swap(array[size-1], array[0]);  
  140.         /// 树大小减一  
  141.         size--;  
  142.         /// 整理树  
  143.         MinHeapify(array, size, 0);  
  144.     }  
  145.     return;  
  146. }  
  147.   
  148. /// --------------       堆排序           ----------------  
  149.   
  150.   
  151. /// --------------       快速排序         ----------------  
  152. /* 
  153.     基本思想 
  154.     通过第一趟排序,将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分小,然后再对这2部分数据进行排序整个过程可以地柜进行。 
  155.     基本介绍 
  156.     首先任意选取一个数据,通常选择第一个元素作为关键数据,然后将所有比它小的数据都放到它的前面,所有比它大的数据都放到它后面。 
  157.   
  158.     一趟快速排序的算法是: 
  159.     1)设置两个变量i、j,排序开始的时候:i=0,j=N-1; 
  160.     2)以第一个数组元素作为关键数据,赋值给key,即key=A[0]; 
  161.     3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key   的值A[j],将A[j]和A[i]互换; 
  162.     4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换; 
  163.     5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。 
  164.   
  165.   
  166.  快排的一个循环  
  167.     从最后找比关键值小的。 
  168.     从前找比关键之大的。 
  169.     合在一起为一个循环。 
  170.  */  
  171. template<typename T>  
  172. void Quick_sort(T array[], int low, int high)  
  173. {  
  174.     if (low >= high)  
  175.     {  
  176.         return ;  
  177.     }  
  178.     int first = low;  
  179.     int last = high;  
  180.     /// 用第一个元素作为关键值  
  181.     int key = array[first];  
  182.       
  183.     /// 一个循环= 从后向前 + 从前向后  
  184.     while (first < last)  
  185.     {  
  186.         /// 从最后开始找比关键值大的元素,找到并交换到关键值得位置  
  187.         while (first < last && array[last] >= key)  
  188.         {  
  189.             --last;  
  190.         }  
  191.         /// 将比第一个小的移动到低端  
  192.         array[first] = array[last];  
  193.           
  194.         while (first < last && array[first] <= key)  
  195.         {  
  196.             ++first;  
  197.         }  
  198.         /// 将比第一个大的移动到高端  
  199.         array[last] = array[first];  
  200.     }  
  201.       
  202.     /// 记录关键值  
  203.     array[first] = key;  
  204.     /// 递归调用  
  205.     Quick_sort(array, low, high);  
  206.     Quick_sort(array, first + 1, high);  
  207. }  
  208. /// --------------       快速排序         ----------------  
  209.   
  210. /// --------------       归并排序         ----------------  
  211.   
  212. /* 
  213.     算法概述 
  214.     该算法是分治法的一个非常典型的应用。 
  215.     算法过程: 
  216.     比较a[i]与a[j]的大小,若a[i]<= a[j],则将第一个表中的元素a[i]复制到r[k]中,令i和K分别加上1; 
  217. 否则,将第二个有序表中的元素a[j]复制到r[k]中,并令k和j分别+1,如此循环下去。归并算法常采用递归实现。 
  218.      
  219.     归并操作示例 
  220.  归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。 
  221.  如 设有数列{6,202,100,301,38,8,1} 
  222.  初始状态:6,202,100,301,38,8,1 
  223.  第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3; 
  224.  第二次归并后:{6,100,202,301},{1,8,38},比较次数:4; 
  225.  第三次归并后:{1,6,8,38,100,202,301},比较次数:4; 
  226.  总的比较次数为:3+4+4=11,; 
  227.  逆序数为14; 
  228.   
  229.  */  
  230. template<typename T>  
  231. void Merege(T *sourceArray, T *aimArray, int startIndex, int midIndex, int endIndex)  
  232. {  
  233.     int i = startIndex;  
  234.     int j = midIndex + 1;  
  235.     int k = endIndex;  
  236.       
  237.       
  238.     while (i != midIndex && j != midIndex)  
  239.     {  
  240.         if (sourceArray[i] >= sourceArray[j])  
  241.         {  
  242.             aimArray[k++] = sourceArray[i++];  
  243.         }  
  244.         else  
  245.         {  
  246.             aimArray[k++] = sourceArray[j++];  
  247.         }  
  248.     }  
  249.       
  250.     /// 把剩下的全部合并到新数组中  
  251.     while (i != midIndex)  
  252.     {  
  253.         aimArray[k++] = sourceArray[i++];  
  254.     }  
  255.     while (j != midIndex)  
  256.     {  
  257.         aimArray[k++] = sourceArray[j++];  
  258.     }  
  259.       
  260.     /// 重新归并数组  
  261.     for (i = startIndex; i <= endIndex; i++)  
  262.     {  
  263.         sourceArray[i] = aimArray[i];  
  264.     }  
  265. }  
  266.   
  267. template<typename T>  
  268. /// 内部使用递归  
  269. void Merege_sort(T *sourceArr, T *aimArr, int startIndex, int endIndex)  
  270. {  
  271.     int midIndex = NULL;  
  272.     if(startIndex < endIndex)  
  273.     {  
  274.         midIndex = (startIndex + endIndex) / 2;  
  275.         Merege_sort(sourceArr, aimArr, startIndex, midIndex);  
  276.         Merege_sort(sourceArr, aimArr, midIndex+1, endIndex);  
  277.         Merege(sourceArr, aimArr, startIndex, midIndex, endIndex);  
  278.     }  
  279. }  
  280.   
  281.   
  282. /// --------------       归并排序         ----------------  

3、示例代码(C++实现)

       注意:导入头文件有:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include <stdlib.h>  
      使用命名空间std;

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. using namespace std;  
//-------------------------   我是分割线 -----------------------

      A 冒泡排序

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void m_Bubble_sort(int *array, int length)  
  2. {  
  3.     for (int i = 0; i < length - 1; i++)  
  4.     {  
  5.         for (int j = 0; j < length - 1 - i; j++)  
  6.         {  
  7.             if (array[j] > array[j+1])  
  8.             {  
  9.                 array[j] = array[j] ^ array[j+1];  
  10.                 array[j+1] = array[j] ^ array[j+1];  
  11.                 array[j] = array[j] ^ array[j+1];  
  12.             }  
  13.         }  
  14.     }  
  15. }  
     B、选择排序

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /// 选择排序  
  2. void m_Selectiont_sort(int *array, int length)  
  3. {  
  4.     int index = NULL;  
  5.       
  6.     for (int i = 0; i < length - 1; i++)  
  7.     {  
  8.         /// 记录位置  
  9.         index = i;  
  10.         for (int j = i + 1; j < length; j++)  
  11.         {  
  12.             /// 判断索引的值是否变化  
  13.             if (array[index] > array[j])  
  14.             {  
  15.                 index = j;  
  16.             }  
  17.         }  
  18.         /// 若不相等,则交换数  
  19.         if (index != i)  
  20.         {  
  21.             array[index] = array[index] ^ array[i];  
  22.             array[i] = array[index] ^ array[i];  
  23.             array[index] = array[index] ^ array[i];  
  24.         }  
  25.     }  
  26. }  

     C、快排

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /// 快速排序, 小的数移动到低端,大的数移动到高端  
  2. void m_Quick_sort(int *array, int low, int high)  
  3. {  
  4.     if (low >= high)  
  5.     {  
  6.         return;  
  7.     }  
  8.     int first = low;  
  9.     int last = high;  
  10.     /// 定义关键字  
  11.     int key = array[first];  
  12.       
  13.     while (first < last)  
  14.     {  
  15.         /// 首先进行的是倒序查找  
  16.         while (last > first && array[last] >= key)  
  17.         {  
  18.             --last;  
  19.         }  
  20.         array[first] = array[last];  
  21.         /// 接着为正序查找  
  22.         while (last > first && array[first] <= key)  
  23.         {  
  24.             ++first;  
  25.         }  
  26.         ///将第一个大的移动到高端  
  27.         array[last] = array[first];  
  28.     }  
  29.       
  30.     /// 记录枢轴关键字,放到高端  
  31.     array[first] = key;  
  32.     /// 递归调用  
  33.     m_Quick_sort(array, low, first - 1);  
  34.     m_Quick_sort(array, first + 1, high);  
  35. }  

    D、输出数组内容函数原型

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /// 数组输出函数  
  2. void showArray(int *array, int length)  
  3. {  
  4.     for (int i = 0; i < length; i++)  
  5.     {  
  6.         cout << array[i] << " ";  
  7.     }  
  8.     cout << endl;  
  9. }  

     E、main函数调用示例

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ///主函数  
  2. int main(int argc, const char * argv[])  
  3. {  
  4.     /// 排序测试数组  
  5.     int array[8] = {4, 3, 2, 1, 0, -1, -2, -3};  
  6.       
  7.     cout << "原数组内容" << endl;  
  8.     for (int i = 0; i < 8; i++)  
  9.     {  
  10.         cout << array[i] << " ";  
  11.     }  
  12.     cout << endl;  
  13.       
  14.     /// 调用快排  
  15.     m_Quick_sort(array, 0, 7);  
  16.       
  17.       
  18.     cout << "排序结果" << endl;  
  19.     showArray(array, 8);  
  20.   
  21.     return 0;  
  22. }  
      F、调用输出结果:


4、代码汇总

       下面的代码,包括我学习排序和复习排序的代码汇总。笔记汇总。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include <stdlib.h>  
  3. #include <bitset>  
  4. using namespace std;  
  5.   
  6. /// --------------       冒泡排序         ----------------  
  7. /* 冒泡排序 
  8.   
  9.  算法原理: 
  10.  1、比较相邻的两个元素,若第一个比第二个大,就交换他们两个 
  11.  2、从第一个到结尾的最后一对,对每一对相邻元素做同样的操作。最后的元素应该是最大的数 
  12.  3、除了最后一个,针对所有的元素重复以上的步骤 
  13.  4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较 
  14.  5、注意:冒泡排序,默认每次都是找的最大或者最小的值,每一轮比较完毕,最后的元素一定是最大或最小的值 
  15.  */  
  16.   
  17. /// 帧数或浮点数皆可使用  
  18. template <typename T>  
  19. void bubble_sort(T *array, int length)  
  20. {  
  21.     /// 计数器  
  22.     int i = 0, j =0;  
  23.       
  24.     ///  
  25.     for (; i < length - 1; i++)  
  26.     {  
  27.         for (j = 0; j < length - 1 - i; j++)  
  28.         {  
  29.             if (array[j] > array[j+1])  
  30.             {  
  31.                 array[j+1] = array[j] ^ array[j+1];  
  32.                 array[j] = array[j] ^ array[j+1];  
  33.                 array[j+1] = array[j] ^ array[j+1];  
  34.             }  
  35.         }  
  36.     }  
  37. }  
  38. /// --------------       冒泡排序         ----------------  
  39.   
  40.   
  41. /// --------------       选择排序         ----------------  
  42. /* 
  43.     原理:每一次从待排序的数据元素中选择出最小的或者最大的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 
  44.     选择排序的第一层循环从开始元素到倒数第二个元素,主要是在每次进入第二层的循环之前,将外层循环下的值给临时变量,接下来的第二层循环中若发现比这个最小的位置的元素更小的元素,则将更小的下表赋给临时变量,最后,在二层循环退出后,若临时变量没有改变,则说明没有改变,有比当前外层循环更小的元素,需要将这两个元素交换 
  45.  */  
  46. template<typename T>  
  47. void selection_sort(T *array, int length)  
  48. {  
  49.     /// 计数器  
  50.     int temp = NULL;  
  51.     T array_temp;  
  52.       
  53.     for (int i= 0; i < length - 1; i++)  
  54.     {  
  55.         /// 记录位置  
  56.         temp = i;  
  57.         for (int j = i + 1; j < length; j++)  
  58.         {  
  59.             if (array[temp] > array[j])  
  60.             {  
  61.                 /// 记录大的值得位置  
  62.                 temp = j;  
  63.             }  
  64.         }  
  65.         /// 这里是二层循环结束的地方  
  66.         if (i != temp)  
  67.         {  
  68.             array_temp = array[temp];  
  69.             array[temp] = array[i];  
  70.             array[i] = array_temp;  
  71.         }  
  72.     }  
  73.       
  74. }  
  75. /// --------------       选择排序         ----------------  
  76.   
  77. /// --------------       堆排序           ----------------  
  78. /*      思想  和 基本操作 
  79.   
  80.  (1)用大根堆排序的基本思想 
  81.  ① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区 
  82.  ② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key 
  83.  ③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。直到无序区只有一个元素为止。 
  84.   
  85.  (2)大根堆排序算法的基本操作: 
  86.  ①建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2) 其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。 
  87.  ②调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,如果最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为是沿着深度方向进行调整的。 
  88.  ③堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn) 
  89.  */  
  90. ///--------整理结点  
  91. template<typename T>  
  92. void MinHeapify(T *array, int size, int element)  
  93. {  
  94.     /// 左右子树  
  95.     int lchild = element * 2 + 1;  
  96.     int rchild = lchild + 1;  
  97.       
  98.     /// 子树均在范围内  
  99.     while (rchild < size)  
  100.     {  
  101.         /// 若左右子树都小  
  102.         if (array[element] < array[lchild] && array[element] < array[rchild])  
  103.         {  
  104.             return;  
  105.         }  
  106.         /// 若左边最小  
  107.         if (array[lchild] < array[rchild])  
  108.         {  
  109.             /// 把左面的提到上面去  
  110.             swap(array[element], array[rchild]);  
  111.             /// 循环时,整理子树  
  112.             element = lchild;  
  113.         }  
  114.         /// 否则右边最小,同理  
  115.         else  
  116.         {  
  117.             swap(array[element], array[rchild]);  
  118.             element = lchild;  
  119.         }  
  120.         /// 重新计算子树的位置  
  121.         lchild = element * 2 + 1;  
  122.         /// 只有左子树且子树小于自己  
  123.         if (lchild < size && array[lchild] < array[element])  
  124.         {  
  125.             swap(array[lchild], array[element]);  
  126.         }  
  127.         return;  
  128.     }  
  129. }  
  130.   
  131. /// ----- 堆排序操作  
  132. template<typename T>  
  133. void Heap_sort(T *array, int size)  
  134. {  
  135.     /// 从子树整理树  
  136.     for (int i = size - 1; i >= 0; i--)  
  137.     {  
  138.         MinHeapify(array, size, i);  
  139.     }  
  140.     /// 拆除树  
  141.     while (size > 0)  
  142.     {  
  143.         /// 将根与数组最末交换  
  144.         swap(array[size-1], array[0]);  
  145.         /// 树大小减一  
  146.         size--;  
  147.         /// 整理树  
  148.         MinHeapify(array, size, 0);  
  149.     }  
  150.     return;  
  151. }  
  152.   
  153. /// --------------       堆排序           ----------------  
  154.   
  155.   
  156. /// --------------       快速排序         ----------------  
  157. /* 
  158.     基本思想 
  159.     通过第一趟排序,将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分小,然后再对这2部分数据进行排序整个过程可以地柜进行。 
  160.     基本介绍 
  161.     首先任意选取一个数据,通常选择第一个元素作为关键数据,然后将所有比它小的数据都放到它的前面,所有比它大的数据都放到它后面。 
  162.   
  163.     一趟快速排序的算法是: 
  164.     1)设置两个变量i、j,排序开始的时候:i=0,j=N-1; 
  165.     2)以第一个数组元素作为关键数据,赋值给key,即key=A[0]; 
  166.     3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key   的值A[j],将A[j]和A[i]互换; 
  167.     4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换; 
  168.     5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。 
  169.   
  170.   
  171.  快排的一个循环  
  172.     从最后找比关键值小的。 
  173.     从前找比关键之大的。 
  174.     合在一起为一个循环。 
  175.  */  
  176. template<typename T>  
  177. void Quick_sort(T array[], int low, int high)  
  178. {  
  179.     if (low >= high)  
  180.     {  
  181.         return ;  
  182.     }  
  183.     int first = low;  
  184.     int last = high;  
  185.     /// 用第一个元素作为关键值  
  186.     int key = array[first];  
  187.       
  188.     /// 一个循环= 从后向前 + 从前向后  
  189.     while (first < last)  
  190.     {  
  191.         /// 从最后开始找比关键值大的元素,找到并交换到关键值得位置  
  192.         while (first < last && array[last] >= key)  
  193.         {  
  194.             --last;  
  195.         }  
  196.         /// 将比第一个小的移动到低端  
  197.         array[first] = array[last];  
  198.           
  199.         while (first < last && array[first] <= key)  
  200.         {  
  201.             ++first;  
  202.         }  
  203.         /// 将比第一个大的移动到高端  
  204.         array[last] = array[first];  
  205.     }  
  206.       
  207.     /// 记录关键值  
  208.     array[first] = key;  
  209.     /// 递归调用  
  210.     Quick_sort(array, low, high);  
  211.     Quick_sort(array, first + 1, high);  
  212. }  
  213. /// --------------       快速排序         ----------------  
  214.   
  215. /// --------------       归并排序         ----------------  
  216.   
  217. /* 
  218.     算法概述 
  219.     该算法是分治法的一个非常典型的应用。 
  220.     算法过程: 
  221.     比较a[i]与a[j]的大小,若a[i]<= a[j],则将第一个表中的元素a[i]复制到r[k]中,令i和K分别加上1; 
  222. 否则,将第二个有序表中的元素a[j]复制到r[k]中,并令k和j分别+1,如此循环下去。归并算法常采用递归实现。 
  223.      
  224.     归并操作示例 
  225.  归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。 
  226.  如 设有数列{6,202,100,301,38,8,1} 
  227.  初始状态:6,202,100,301,38,8,1 
  228.  第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3; 
  229.  第二次归并后:{6,100,202,301},{1,8,38},比较次数:4; 
  230.  第三次归并后:{1,6,8,38,100,202,301},比较次数:4; 
  231.  总的比较次数为:3+4+4=11,; 
  232.  逆序数为14; 
  233.   
  234.  */  
  235. template<typename T>  
  236. void Merege(T *sourceArray, T *aimArray, int startIndex, int midIndex, int endIndex)  
  237. {  
  238.     int i = startIndex;  
  239.     int j = midIndex + 1;  
  240.     int k = endIndex;  
  241.       
  242.       
  243.     while (i != midIndex && j != midIndex)  
  244.     {  
  245.         if (sourceArray[i] >= sourceArray[j])  
  246.         {  
  247.             aimArray[k++] = sourceArray[i++];  
  248.         }  
  249.         else  
  250.         {  
  251.             aimArray[k++] = sourceArray[j++];  
  252.         }  
  253.     }  
  254.       
  255.     /// 把剩下的全部合并到新数组中  
  256.     while (i != midIndex)  
  257.     {  
  258.         aimArray[k++] = sourceArray[i++];  
  259.     }  
  260.     while (j != midIndex)  
  261.     {  
  262.         aimArray[k++] = sourceArray[j++];  
  263.     }  
  264.       
  265.     /// 重新归并数组  
  266.     for (i = startIndex; i <= endIndex; i++)  
  267.     {  
  268.         sourceArray[i] = aimArray[i];  
  269.     }  
  270. }  
  271.   
  272. template<typename T>  
  273. /// 内部使用递归  
  274. void Merege_sort(T *sourceArr, T *aimArr, int startIndex, int endIndex)  
  275. {  
  276.     int midIndex = NULL;  
  277.     if(startIndex < endIndex)  
  278.     {  
  279.         midIndex = (startIndex + endIndex) / 2;  
  280.         Merege_sort(sourceArr, aimArr, startIndex, midIndex);  
  281.         Merege_sort(sourceArr, aimArr, midIndex+1, endIndex);  
  282.         Merege(sourceArr, aimArr, startIndex, midIndex, endIndex);  
  283.     }  
  284. }  
  285.   
  286.   
  287. /// --------------       归并排序         ----------------  
  288.   
  289.   
  290.   
  291.   
  292.   
  293.   
  294.   
  295. /*  排序总结 */  
  296. /// 冒泡排序  
  297. void m_Bubble_sort(int *array, int length)  
  298. {  
  299.     for (int i = 0; i < length - 1; i++)  
  300.     {  
  301.         for (int j = 0; j < length - 1 - i; j++)  
  302.         {  
  303.             if (array[j] > array[j+1])  
  304.             {  
  305.                 array[j] = array[j] ^ array[j+1];  
  306.                 array[j+1] = array[j] ^ array[j+1];  
  307.                 array[j] = array[j] ^ array[j+1];  
  308.             }  
  309.         }  
  310.     }  
  311. }  
  312.   
  313. /// 选择排序  
  314. void m_Selectiont_sort(int *array, int length)  
  315. {  
  316.     int index = NULL;  
  317.       
  318.     for (int i = 0; i < length - 1; i++)  
  319.     {  
  320.         /// 记录位置  
  321.         index = i;  
  322.         for (int j = i + 1; j < length; j++)  
  323.         {  
  324.             /// 判断索引的值是否变化  
  325.             if (array[index] > array[j])  
  326.             {  
  327.                 index = j;  
  328.             }  
  329.         }  
  330.         /// 若不相等,则交换数  
  331.         if (index != i)  
  332.         {  
  333.             array[index] = array[index] ^ array[i];  
  334.             array[i] = array[index] ^ array[i];  
  335.             array[index] = array[index] ^ array[i];  
  336.         }  
  337.     }  
  338. }  
  339.   
  340.   
  341. /// 快速排序, 小的数移动到低端,大的数移动到高端  
  342. void m_Quick_sort(int *array, int low, int high)  
  343. {  
  344.     if (low >= high)  
  345.     {  
  346.         return;  
  347.     }  
  348.     int first = low;  
  349.     int last = high;  
  350.     /// 定义关键字  
  351.     int key = array[first];  
  352.       
  353.     while (first < last)  
  354.     {  
  355.         /// 首先进行的是倒序查找  
  356.         while (last > first && array[last] >= key)  
  357.         {  
  358.             --last;  
  359.         }  
  360.         array[first] = array[last];  
  361.         /// 接着为正序查找  
  362.         while (last > first && array[first] <= key)  
  363.         {  
  364.             ++first;  
  365.         }  
  366.         ///将第一个大的移动到高端  
  367.         array[last] = array[first];  
  368.     }  
  369.       
  370.     /// 记录枢轴关键字,放到高端  
  371.     array[first] = key;  
  372.     /// 递归调用  
  373.     m_Quick_sort(array, low, first - 1);  
  374.     m_Quick_sort(array, first + 1, high);  
  375. }  
  376.   
  377.   
  378.   
  379.   
  380.   
  381.   
  382. /// 快排  
  383. void new_Quick_sort(int *array, int low, int high)  
  384. {  
  385.     if (low >= high)  
  386.     {  
  387.         return;  
  388.     }  
  389.     int first = low;  
  390.     int last = high;  
  391.     int key = array[first];  
  392.       
  393.     /// first = last ,结束  
  394.     while (first < last)  
  395.     {  
  396.         /// 倒序找,小的, 交换  
  397.         while (first < last && array[last] >= key)  
  398.         {  
  399.             --last;  
  400.         }  
  401.         array[first] = array[last];  
  402.           
  403.         ///  正序找,大的,交换  
  404.         while (first < last && array[first] <= key)  
  405.         {  
  406.             ++first;  
  407.         }  
  408.         array[last] = array[first];  
  409.     }  
  410.     array[first] = key;  
  411.     new_Quick_sort(array, low, first - 1);  
  412.     new_Quick_sort(array, first + 1, high);  
  413. }  
  414.   
  415. /// 快排  
  416. void m_new_Quick_sort(int *array, int low, int high)  
  417. {  
  418.     if (low >= high)  
  419.     {  
  420.         return;  
  421.     }  
  422.       
  423.     int first = low;  
  424.     int last = high;  
  425.     int key = array[first];  
  426.       
  427.     while (first < last)  
  428.     {  
  429.         while (first < last && array[last] >= key)  
  430.         {  
  431.             --last;  
  432.         }  
  433.         array[first] = array[last];  
  434.           
  435.         while (first < last && array[first] <= key)  
  436.         {  
  437.             ++first;  
  438.         }  
  439.         array[last] = array[first];  
  440.     }  
  441.       
  442.     ///  
  443.     array[first] = key;  
  444.     m_new_Quick_sort(array, low, first - 1);  
  445.     m_new_Quick_sort(array, first + 1, high);  
  446.       
  447. }  
  448.   
  449. /// 数组输出函数  
  450. void showArray(int *array, int length)  
  451. {  
  452.     for (int i = 0; i < length; i++)  
  453.     {  
  454.         cout << array[i] << " ";  
  455.     }  
  456.     cout << endl;  
  457. }  
  458.   
  459.   
  460. ///----- 归并排序  
  461. void m_Merege(int *sourceArray, int *aimArray, int startIndex, int midIndex, int endIndex)  
  462. {  
  463.     int i = startIndex;  
  464.     int j = midIndex + 1;  
  465.     int k = startIndex;  
  466.       
  467.       
  468.     while (i != midIndex+1 && j != endIndex + 1)  
  469.     {  
  470.         if (sourceArray[i] >= sourceArray[j])  
  471.         {  
  472.             aimArray[k++] = sourceArray[j++];  
  473.         }  
  474.         else  
  475.         {  
  476.             aimArray[k++] = sourceArray[i++];  
  477.         }  
  478.     }  
  479.       
  480.     /// 把剩下的全部合并到新数组中  
  481.     while (i != midIndex+1)  
  482.     {  
  483.         aimArray[k++] = sourceArray[i++];  
  484.     }  
  485.     while (j != midIndex+1)  
  486.     {  
  487.         aimArray[k++] = sourceArray[j++];  
  488.     }  
  489.       
  490.     /// 重新组合数组  
  491.     for (i = startIndex; i <= endIndex; i++)  
  492.     {  
  493.         sourceArray[i] = aimArray[i];  
  494.     }  
  495. }  
  496.   
  497. /// 内部使用递归  
  498. void m_Merege_sort(int *sourceArr, int *aimArr, int startIndex, int endIndex)  
  499. {  
  500.     int midIndex = NULL;  
  501.     if(startIndex < endIndex)  
  502.     {  
  503.         midIndex = (startIndex + endIndex) / 2;  
  504.         m_Merege_sort(sourceArr, aimArr, startIndex, midIndex);  
  505.         m_Merege_sort(sourceArr, aimArr, midIndex+1, endIndex);  
  506.         m_Merege(sourceArr, aimArr, startIndex, midIndex, endIndex);  
  507.     }  
  508. }  
  509.   
  510.   
  511.   
  512.   
  513. /// 快排_  
  514. void m_Quick_mem_sort(int *arr, int low, int high)  
  515. {  
  516.     if (low >= high)  
  517.     {  
  518.         return;  
  519.     }  
  520.       
  521.     int first = low;  
  522.     int last = high;  
  523.     int key = arr[first];  
  524.       
  525.       
  526.     while (first < last)  
  527.     {  
  528.         while (first < last && arr[last] >= key){--last;}  
  529.         arr[first] = arr[last];  
  530.         while (first < last && arr[first] <= key) {++first;}  
  531.         arr[last] = arr[first];  
  532.     }  
  533.     arr[first] = key;  
  534.     m_Quick_mem_sort(arr, low, first - 1);  
  535.     m_Quick_mem_sort(arr, first+1, high);  
  536. }  
  537.   
  538.   
  539. /// 复习快排  
  540. void quick_sort_review(int *array, int low, int high)  
  541. {  
  542.     if (low >= high)  
  543.     {  
  544.         return;  
  545.     }  
  546.     int first = low;  
  547.     int last = high;  
  548.     int key = array[first];  
  549.       
  550.     while (first < last)  
  551.     {  
  552.         while (first < last && array[last] >= key)  
  553.         {  
  554.             --last;  
  555.         }  
  556.         array[first] = array[last];  
  557.         while (first < last && array[first] <= key)  
  558.         {  
  559.             ++first;  
  560.         }  
  561.         array[last] = array[first];  
  562.     }  
  563.       
  564.     array[first] = key;  
  565.       
  566.     quick_sort_review(array, low, first - 1);  
  567.     quick_sort_review(array, first + 1, high);  
  568. }  
  569.   
  570.   
  571.   
  572. /// 冒泡复习  
  573. void bubble_sort_review(int *arr, int length)  
  574. {  
  575.     for (int i = 0; i < length - 1; i++)  
  576.     {  
  577.         for (int j = 0; j < length - 1 - i; j++)  
  578.         {  
  579.             if (arr[j] >= arr[j+1])  
  580.             {  
  581.                 arr[j] = arr[j] ^ arr[j+1];  
  582.                 arr[j+1] = arr[j] ^ arr[j+1];  
  583.                 arr[j] = arr[j] ^ arr[j+1];  
  584.             }  
  585.         }  
  586.     }  
  587. }  
  588.   
  589.   
  590. /// 选择排序学习  
  591. void select_sort_review(int *arr, int length)  
  592. {  
  593.     int index = NULL;  
  594.       
  595.     for (int i = 0; i < length - 1; i++)  
  596.     {  
  597.         index = i;  
  598.         for (int j = i; j < length; j++)  
  599.         {  
  600.             if (arr[j] < arr[index])  
  601.             {  
  602.                 index = j;  
  603.             }  
  604.         }  
  605.         if (i != index)  
  606.         {  
  607.             arr[index] = arr[i] ^ arr[index];  
  608.             arr[i] = arr[i] ^ arr[index];  
  609.             arr[index] = arr[i] ^ arr[index];  
  610.         }  
  611.     }  
  612. }  
  613.   
  614.   
  615. ///主函数  
  616. int main(int argc, const char * argv[])  
  617. {  
  618.     /// 排序测试数组  
  619.     int array[8] = {4, 3, 2, 1, 0, -1, -2, -3};  
  620.       
  621.     cout << "原数组内容" << endl;  
  622.     for (int i = 0; i < 8; i++)  
  623.     {  
  624.         cout << array[i] << " ";  
  625.     }  
  626.       
  627.     /// 快排复习  
  628. //    quick_sort_review(array, 0, 7);  
  629. //    showArray(array, 8);  
  630.   
  631. //    ///冒泡复习  
  632. //    bubble_sort_review(array, 8);  
  633. //    cout << endl;  
  634.       
  635.     /// 选择复习  
  636.     cout << endl;  
  637.     select_sort_review(array, 8);  
  638.       
  639.     cout << "排序结果" << endl;  
  640.     showArray(array, 8);  
  641.   
  642.   
  643.     return 0;  
  644. }  
0 0
原创粉丝点击