【Algothrim】堆排序
2017-03-16 11:51
447 查看
性能最好的排序之一,除了归并,就是堆。
时间复杂度是:o(logn)
空间复杂度:o(1)
不是一个稳定的排序
有四种不稳定的排序:快速 选择 希尔 堆
排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前 和排序后他们的相对位置不发生变化
堆排序用的数据结构是用数组来表示一颗完全二叉树
完全二叉树是效率很高的数据结构
完全二叉树是只有最下面的两层结点度能够小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树
算法的实现分为2步,
1, 建立最大堆
从第一个非叶子节点开始,length/2-1
如果有2个孩子,则将两个孩子里大的该节点交换
交换后,如果这个孩子节点有孩子,会导致该孩子节点作为父节点的时候不是最大堆,那么再交换长最大堆
2, 交换后调整
建立最大堆后,根节点就是最大值,和最后一个交换
去掉最后一个节点,将剩下的节点重新建立最大堆
实现
运行结果
Orignal list is ...
9 7 6 41 78 54 232 52 42 10
New list is ...
7 6 9 10 41 42 52 54 78 232
时间复杂度是:o(logn)
空间复杂度:o(1)
不是一个稳定的排序
有四种不稳定的排序:快速 选择 希尔 堆
排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前 和排序后他们的相对位置不发生变化
堆排序用的数据结构是用数组来表示一颗完全二叉树
完全二叉树是效率很高的数据结构
完全二叉树是只有最下面的两层结点度能够小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树
算法的实现分为2步,
1, 建立最大堆
从第一个非叶子节点开始,length/2-1
如果有2个孩子,则将两个孩子里大的该节点交换
交换后,如果这个孩子节点有孩子,会导致该孩子节点作为父节点的时候不是最大堆,那么再交换长最大堆
2, 交换后调整
建立最大堆后,根节点就是最大值,和最后一个交换
去掉最后一个节点,将剩下的节点重新建立最大堆
实现
#include <iostream> using namespace std; void myprint(int a[], int n) { int i = 0; for (i = 0; i < n; i++) { printf("%d\t", a[i]); } printf("\n"); } void adjust(int a[], int i, int n) { while (i < n) { int lchild = 2 * i + 1; if (lchild + 1 < n && a[lchild + 1] > a[lchild]) lchild++; if (lchild<n-1 && a[lchild] >a[i]) { int temp = a[i]; a[i] = a[lchild]; a[lchild] = temp; i = lchild;//交换了这个孩子,导致这个孩子作为根节点的情况被改变,所以要重新调整 } else { break;//没有引起变化,无须调整 } } } void mysort(int a[], int n) { int i = n / 2 - 1; for (; i >=0; i--) { adjust(a,i,n); } for (i = n - 1; i >= 0; i--) { int temp = a[i]; a[i] = a[0]; a[0] = temp; adjust(a,0,i); } } int main() { int a[10] = { 9, 7, 6, 41, 78, 54, 232, 52, 42, 10 }; printf("Orignal list is ...\n"); myprint(a, 10); mysort(a, 10); printf("New list is ...\n"); myprint(a, 10); return 0; }
运行结果
Orignal list is ...
9 7 6 41 78 54 232 52 42 10
New list is ...
7 6 9 10 41 42 52 54 78 232