【内部排序】 交换排序与选择排序详解

来源:互联网 发布:江西省干部网络 编辑:程序博客网 时间:2024/05/20 18:47


交换排序:通过依次交换逆序的元素使其有序化的过程。


介绍两种交换排序: 冒泡排序,快速排序


冒泡法:从第一个元素开始,依次比较相邻的两个元素,如果逆序则交换,第一趟比较结束后,序列中最大的元素将移动到序列末尾,即第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///      <在此添加示例代码>/// @endcodevoid 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;}




3 2
原创粉丝点击