【选择排序】和【堆排序】
2017-07-13 18:57
197 查看
一、选择排序
(1)选择排序的算法思路(假设升序)每次从待排序的区间中找到一个最小数,然后将这个最小数和该区间的第一个数交换数值;然后缩小区间,继续这样的的方法,最终到该待排区间为一个数时停止,排序完成;
总体算法分三步完成:选数据—>将所选数据放入合适位置—>缩小需要排序的范围
(2)图说
(3)程序
#include<iostream> #include<assert.h> using namespace std; ---------//核心代码 void SelectSort(int* arr,int sz)//sz为数组的尾下标 { assert(arr); int left=0;//记录待排序区间的首下标 while(left<sz) { int min=left;//记录待排序区间的最小值的小标 int begin=left;//遍历待排序区间 //while循环用于寻找待排序区间的最小值,并用min记住最小值下标 while (begin<=sz) { if (arr[min]>arr[begin]) { min=begin;//更新最小值的下标 } ++begin;//比较下一个数字 } swap(arr[left],arr[min]);//将该区间的最小值放在该区间的首位; ++left;//缩小待排序区间 } } ---------- void Printf(int* arr,int sz) { assert(arr); int i=0; while (i<sz) { cout<<arr[i]<<" "; i++; } } int main() { int a[]={5,6,7,9,3,4,1,2}; int sz=sizeof(a)/sizeof(a[0]); SelectSort(a,sz-1); Printf(a,sz); return 0; }
(4)测试结果:
(5)选择排序的优化
上面的选择排序的写法每次只能在待排序的区间中寻找出一个最小的数,那么一共要寻找N趟,每趟比较和交换N次;所以时间复杂度为O(N^2);
选择排序的优化是,每趟从待排序区间找出两个数,一个最大数,一个最小数,最小数放待排序区间的第一位,最大数放待排序区间的最后一位;
这样只需要寻找N/2趟;
(5.1)优化后的图解
(5.2)优化后的选择排序的程序
#include<iostream> #include<assert.h> using namespace std; ----------//选择排序的优化 void SelectSort(int* arr,int sz) { assert(arr); int left=0;//待排序区间的首下标 int right=sz;//待排序区间的尾下标 while (left<right) { int min=left;//记录最小值的小标 int max=right;//记录最大值的下标 int begin=left;//遍历待排序区间 while (begin<=right)//一趟排序下来找到一个最大值一个最小值 { if (arr[min]>arr[begin]) { min=begin; } if (arr[max]<arr[begin]) { max=begin; } ++begin; } swap(arr[min],arr[left]);//将小值放在区间的第一位 if(max==left)//处理最大值为第一个输的情况,此时经过上面最小值和地址为元素的交换,此时最大值放在min下标的位置 { max=min;//将最大值小标更新交换以后的最小值的下标处,此时该处存放的是最大值 } swap(arr[max],arr[right]);//将最大值放在区间的最后一位 ++left; --right; } } ---------- void Printf(int* arr,int sz) { assert(arr); int i=0; while (i<sz) { cout<<arr[i]<<" "; i++; } } int main() { int a[]={5,6,7,9,3,4,1,2}; int sz=sizeof(a)/sizeof(a[0]); SelectSort(a,sz-1); Printf(a,sz); return 0; }
(6)选择排序的时间复杂度&&空间复杂度
时间复杂度:O(N^2)
空间复杂度:O(1)
二、堆排序
1.堆排序的思想:
假设升序排列,先将一个待排序的数组建成大堆,然后这时这个数的第一个数即堆顶的元素就是最大值,那么这时候将堆顶的元素和数组的最后一个元素交换;这时最后一个位置的元素就是将这些数排列好后的最大值应该待的位置;这时候将剩下的元素继续调成大堆;由于之前是将首尾元素相交换,所以每次是都从第一个元素开始,向下调整堆为大堆;调整好以后继续重复上面的操作;直到数组的待排序元素只剩一个时,就不用交换调堆,该数就是最小的数,就应该放在第一个位置;排序结束;升序—建大堆 ; 降序—建小堆
2.时间复杂度
每次调堆O(lgN);一共拿N次元素;所以时间复杂度O(N*lgN)
3.代码实现
//堆排:升序---建大堆 ; 降序---建小堆 #include<iostream> using namespace std; #include<cassert> ----------*******************核心代码********************************* //向下调堆 void AdjustDown(int* arr,int father,int sz) { assert(arr); int child=father*2+1; while (child<sz) { //找到左右孩子较大的一个 if (child+1<sz&&arr[child+1]>arr[child]) { child++; } if (child<sz&&arr[father]<arr[child]) { swap(arr[father],arr[child]); father=child; child=father*2+1; } else return ; } } void HeapSort(int* arr,int sz) { assert(arr&&sz>0); //1.建大堆 for (int i=(sz-2)/2;i>=0;i--) { AdjustDown(arr,i,sz); } //2.交换首尾元素;继续调堆 while (sz>1)//待排序的元素个数必须大于一个 { sz--; swap(arr[0],arr[sz]); AdjustDown(arr,0,sz); } } ---------*******************核心代码********************************* int main() { int arr[]={6,4,5,2,9,8,1}; int sz=sizeof(arr)/sizeof(arr[0]); HeapSort(arr,sz); for (int i=0;i<sz;i++) { cout<<arr[i]<<" "; } cout<<endl; return 0; }
相关文章推荐
- 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 排序算法总结---树形选择排序,堆排序
- 各种排序算法实现——基数排序、归并排序、插入排序、冒泡排序、选择排序、快速排序、堆排序、希尔排序
- 8.2 内部排序法---选择类排序(简单选择、堆排序)
- 【Java】八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序 、快速排序、归并排序、堆排序和LST基数排序
- 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现)
- 八大排序算法之四选择排序—堆排序(Heap Sort)
- 冒泡排序,插入排序,快速排序,归并排序,堆排序,选择排序,希尔排序
- 排序大全【各种排序】:直接插入,折半插入,冒泡,快排,简单选择,堆排序,归并排序
- 排序算法--选择排序(简单选择排序、堆排序)java实现
- 9.选择排序——堆排序
- 选择类排序-堆排序 简单选择排序
- 常用排序算法(包括:选择排序,堆排序,冒泡排序,选择排序,快速排序,归并排序)
- 排序 - [选择排序 - 堆排序]
- C语言:数组排序(插入排序、选择排序、泡排序、谢尔排序、快速排序、堆排序)
- 经典排序算法设计与分析(插入排序、冒泡排序、选择排序、shell排序、快速排序、堆排序、分配排序、基数排序、桶排序、归并排序)
- java实现各种基础排序(冒泡排序、快速排序、直接选择排序、堆排序、直接插入排序、归并排序)
- 第十六周项目5—选择排序之堆排序
- 选择 冒泡 插入 快排 堆排序 排序
- 选择排序(简单选择排序--改进的简单选择排序--堆排序)