选择类排序:直接选择与堆排
2017-03-28 09:48
218 查看
直接选择排序:整个数组分为有序区和无序区
思想一开始整个数组默认是无序区,有序区元素为空,每趟从无序区里面选出一个最小的元素,与无序区的第一个元素进行交换,整个时候有序区的元素的元素+1,无序区的元素会-1,下一趟排序再从无序区选择一个最小的与无序区的元素进行交换,无序区元素-1.有序区+1,以后执行同样的操作
代码如下
void selectSort(int a[],int n){ for (int i = 0; i<n; i++) { int min = a[i];//遍历序列,每次以当前遍历的元素作为最小值 int small = i; //内部循环,寻找无序区中的最小值 for (int j = i+1; j<n; j++) { //如果min比较大,那就把小的那个下标记住 if (min>a[j]) { min = a[j]; small = j;//记录每趟选择之后的那个最小值的下标 } } //当最小值的下标不是当前元素的时候 if (small!=i) { //将最小值与无序区的第一个元素交换 int temp = a[small]; a[small] = a[i]; a[i] = temp; } } }
算法效率
时间复杂度:O(n); 空间复杂度: O(1); 不稳定排序
直接选择排序的优化之一:对于重复出现的元素,可以记录他的出现次数,最后直接放入数组中就可以
优化之二:堆排:记录之前比较过得记录,防止重复比较
堆排:大顶堆和小顶堆(以下例子对于大顶堆)
思想:1:构建堆:将数组中的元素构建成一棵完全二叉树
2:初始化堆:对完全二叉树进行调整
* 从最后一个非叶子节点开始,在当前节点以及其左右孩子街节点里面找出一个最大的节点,然后与当前节点交换,其他的也做同样操作,直到根节点位置。
3:排序:每次取出堆的根节点,然后将它与最后一个叶子节点交换,若交换之后破坏了堆的规则,则要重新对堆进行调整,后面进行递归操作
* 规律就是父节点元素大于或者等于左右孩子节点的元素 * 调整规则就是在每个堆里面的父节点以及左右孩子节点中找到一个最大的然后与当前堆里面的父节点节点交换,要是调整之后破坏了其他堆的规则,也要对其他堆重新进行调整
2:算法效率:
时间复杂度:由于每次重新恢复堆的时间复杂度为O(logN),共N - 1次重新恢复堆操作,再加上前面建立堆时N / 2次向下调整,每次调整时间复杂度也为O(logN)。二次操作时间相加还是O(N * logN)。故堆排序的时间复杂度为O(N * logN) 空间复杂度:O(1) 不稳定排序
3:总结:堆排是每次从前面选择最小或者最大元素,然后将其插入后面的有序区,类似于直接选择排序,采用最小堆得到的是递减的,采用最大堆得到递增序列。
堆排和直接选择排序的比较
直接选择排序中要从 a[0]~a[n-1]个选择一个最小的,需要进行 n-1次比较,要从 a[1]~a[n-1]选择一个最小的又要进行 n-2次比较,但这些比较中的有些可能已经在之前 n-1次比较时候比较过,所以就没有必要,堆排利用树形结构记录了以前的比较记录,所以可以减少重复比较次数,对于大量数据来说优势明显相关文章推荐
- C语言实现选择排序、直接插入排序、冒泡排序的示例
- 算法 排序算法之选择排序--直接选择排序和堆排序
- 直接选择排序
- 排序算法-之选择排序(直接选择排序,堆排序)
- 第十六周 -项目1 -(5)直接选择排序
- Java排序算法(二):直接选择排序
- 第十六周项目1(5)验证算法——直接选择排序
- 冒泡排序、直接插入排序、选择插入排序
- 第16周项目1-直接选择排序
- 常用排序算法之选择排序 ( 直接选择排序、堆排序 )
- C# 常用排序方法 冒泡排序,直接选择排序,直接插入排序
- 直接选择排序与反转排序
- 直接选择排序----java实现
- 冒泡,简单选择,直接插入排序(Java版)
- 冒泡排序、直接插入排序及选择排序之Java实现
- 排序算法系列——直接选择排序
- 比较排序总结——直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序
- 直接选择排序
- 直接选择排序
- 直接选择排序