交换排序:通过依次交换逆序的元素使其有序化的过程。
介绍两种交换排序: 冒泡排序,快速排序
冒泡法:从第一个元素开始,依次比较相邻的两个元素,如果逆序则交换,第一趟比较结束后,序列中最大的元素将移动到序列末尾,即第n个位置,第二趟将次大元素移动到n-1位置…… 多趟比较后,会形成有序序列,排序方法类似气泡慢慢向上浮动,因此成为冒泡法。
快速排序: 对冒泡的改进,将序列中的关键字和指定元素(枢轴)比较,将序列以枢轴划分,保证枢轴大于其左边所有数,小于其右边所有数。
(枢轴的选取很关键,避免快排在局部有序数列中退化,再次使用的三者取中法)
按照以上方法,对上次划分的子序列进行递归划分,知道每个子序列只剩下一个元素不能划分为止,此时序列有序。
代码实现:
#include<iostream> #define SIZE 21 typedef int Sqlist[SIZE]; using namespace std; void swap(int &a, int &b) { a = a^b; b = a^b; a = a^b; } //==================================BubbleSort()================================== /// @brief <对函数进行概括说明> 冒泡排序 /// /// <对函数进行详细说明> 内部排序,稳定排序,交换排序 时间复杂度:平均 O(n),最坏O(n^2) /// /// @param [in, out] sq <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 数组 /// @param [in, out] n <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 数组大小 /// /// @return <返回值说明,可以配合使用DocGenList或DocGenTable> 无返回值 /// /// @remark <函数特别说明> 使用引用 /// /// @code /// <在此添加示例代码> /// @endcode void BubbleSort(Sqlist &sq, int n) { cout << "冒泡排序:" << endl; for (int i = 0; i < n - 1; ++i) { for (int j = 0; j < n - i - 1; ++j) { if (sq[j] > sq[j + 1]) { swap(sq[j],sq[j+1]); } } } } ///////////////////////////////////////////////////// //================================PivotkeySelect()================================ /// @brief <对函数进行概括说明> 枢轴选取 /// /// <对函数进行详细说明> 三者取中 /// //================================================================================ int PivotkeySelect(Sqlist &sq, int low, int high) { int mid = low + ((high - low) >> 1);//计算数组中间的元素的下标 //使用三数取中法选择枢轴 if (sq[mid] > sq[high])//目标: sq[mid] <= sq[high] { swap(sq[mid], sq[high]); } if (sq[low] > sq[high])//目标: sq[low] <= sq[high] { swap(sq[low], sq[high]); } if (sq[mid] > sq[low]) //目标: sq[low] >= sq[mid] { swap(sq[mid], sq[low]); } //此时,sq[mid] <= sq[low] <= sq[high] return sq[low]; //low的位置上保存这三个位置中间的值 //分割时可以直接使用low位置的元素作为枢轴,而不用改变分割函数了 } //==================================Partition()================================= /// @brief <对函数进行概括说明> 划分 /// /// <对函数进行详细说明> 用枢轴将数组划分 /// /// @sa <可以参考的类或函数,用空格分隔,函数名称后必须加()> PivotkeySelect() //================================================================================ int Partition(Sqlist &sq, int low, int high) { int key = PivotkeySelect(sq,low,high); //辅助空间 while (low < high) { while (low < high && sq[high] >= key) { high--; } sq[low] = sq[high]; while (low < high && sq[low] <= key) { low++; } sq[high] = sq[low]; } sq[low] = key; return low; } //==================================QuickSort()================================= /// @brief <对函数进行概括说明> 快速排序 对冒泡的改进 不稳定 /// /// <对函数进行详细说明> 将关键字与指定元素比较 递归 时间复杂度:平均O(nlog2^n) 最坏O(n^2) /// /// @param [in, out] sq <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 数组 /// @param [in, out] low <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 最小下标 /// @param [in, out] high <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> 最大下标 /// /// @return <返回值说明,可以配合使用DocGenList或DocGenTable> 返回low /// /// @remark <函数特别说明> /// /// @code /// <在此添加示例代码> /// @endcode /// /// @sa <可以参考的类或函数,用空格分隔,函数名称后必须加()> Partition() PivotkeySelect() //================================================================================ void QuickSort(Sqlist &sq, int low, int high) { if (low < high) { int prvitloc = Partition(sq, low, high); //将数组一分为二 QuickSort(sq, low, prvitloc - 1); //左半部分排序 QuickSort(sq, prvitloc + 1, high); } }
对于n个元素的序列,第一趟经n-1此比较,选出最小的放在第一个位置,第二趟从n-1个元素中,经过n-2次比较,选出最小的放在第二个位置……直到没有待比较的元素。
代码实现:
//====================================MinKey()==================================== /// @brief <对函数进行概括说明> 最小值选取 /// /// <对函数进行详细说明> 从key位置开始,找出大小为n数组中的最小值,并返回下标 /// /// @param [in, out] sq <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> /// @param [in, out] n <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> /// @param [in, out] key <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> /// //================================================================================ int MinKey(Sqlist &sq, int n, int key) { int k = key + 1; for (; k < n; ++k) { if (sq[k] < sq[key]) //若小于则记录下标 { key = k; } } return key; } //==================================SelectSort()================================== /// @brief <对函数进行概括说明> 简单选择排序 /// /// <对函数进行详细说明> n个元素,第一次n-1次比较,选出n个中最小元素,放在序列最前面 /// /// @param [in, out] sq <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> /// @param [in, out] n <参数说明,[in, out]表示参数的传递方向,需要根据情况进行选择> /// /// @return <返回值说明,可以配合使用DocGenList或DocGenTable> /// /// @remark <函数特别说明> /// /// @code /// <在此添加示例代码> /// @endcode /// /// @sa <可以参考的类或函数,用空格分隔,函数名称后必须加()> MinKey() swap() //================================================================================ void SelectSort(Sqlist &sq, int n) { for (int i = 0; i < n - 1; ++i) { int j = MinKey(sq, n, i); if (i != j) swap(sq[i],sq[j]); } }
void main(void) { Sqlist sq = { 49, 38, 65, 97, 76, 13, 27, 49 }; Sqlist sq2 = { 49, 38, 65, 97, 76, 13, 27, 49 }; Sqlist sq3 = { 49, 38, 65, 97, 76, 13, 27, 49 }; cout << "原数组为:" << endl; for (int i = 0; i < 8; ++i) { cout << sq[i]<<" "; } cout << endl; //////////////////////////////////////////// BubbleSort(sq,8); for (int i = 0; i < 8; ++i) { cout << sq[i] << " "; } cout << endl; ///////////////////////////////////////////// cout << "原数组为:" << endl; for (int i = 0; i < 8; ++i) { cout << sq2[i] << " "; } cout << endl; QuickSort(sq2, 0, 7); cout << "快速排序:" << endl; for (int i = 0; i < 8; ++i) { cout << sq2[i] << " "; } cout << endl; ////////////////////////////////////// cout << "原数组为:" << endl; for (int i = 0; i < 8; ++i) { cout << sq3[i] << " "; } cout << endl; SelectSort(sq3, 8); cout << "交换排序:" << endl; for (int i = 0; i < 8; ++i) { cout << sq3[i] << " "; } cout << endl; }
原文地址:http://blog.csdn.net/irean_lau/article/details/46530391