堆排序

来源:互联网 发布:gif软件制作工具 编辑:程序博客网 时间:2024/06/05 18:23

/**
堆:是一棵完全二叉树,并且满足父母优势原则(每个结点的键值都要大于等于它子女的键值,对于叶子结点该条件默认满足)。
数据结构:通常用数组来表示,a[0...n-1]表示表示有n个结点的一棵完全二叉树,点a[i]的左右孩子分别为a[2*i+1]和a[2*i+2]。
构造堆的方式有两种:
1.自底向上:从最后一个父母结点(a[n/2-1])开始,到树根(a[0])为止,检查这些结点是否满足父母优势原则,若不满足则调整(注意:调整后,要再次对与其交换的子女结点进行调整,直到满足父母优势)
2.自顶向下:依次插入新结点到已经构造好的堆中(插到最后一个),再重新构造堆,方法是将新结点与其父母比较,若大于其父母的键值则交换(一直执行该操作直到满足父母优势,此时则新加入的结点被插入到了合适的位置)
时间复杂度:
方式1:可以证明,对于n个结点,构造堆只需不到2n次比较就能完成。
方式2:构造堆的复杂度为O(n*logn)。
堆的插入和删除操作的时间复杂度都属于O(logn)
**/

/* 调整堆。   以root为根的子树原本是一个堆,在对root进行修改后,就要从root开始检测,   若父母优势条件已被破坏则进行调整。可以用递归实现,也可以用非递归*/void heapAdjust(int a[], int root, int len){int maxIndex = root;while (2*root + 1 < len){if (a[2*root+1] > a[maxIndex])maxIndex = 2*root + 1;if (2*root+2 < len && a[2*root+2] > a[maxIndex])maxIndex = 2*root + 2;if (maxIndex != root){swap(a[root], a[maxIndex]);root = maxIndex;}elsebreak;}}/* 递归实现的“调整堆” */void heapAdjustRec(int a[], int root, int len){if (2*root + 1 >= len)return;int maxIndex = root;if (a[2*root+1] > a[maxIndex])maxIndex = 2*root + 1;if (2*root+2 < len && a[2*root+2] > a[maxIndex])maxIndex = 2*root + 2;if (maxIndex != root){swap(a[root], a[maxIndex]);heapAdjust(a, maxIndex, len);}elsereturn;}/* 堆排序。参数为待排序的数组 a[0...n-1] */void heapSort(int a[], int n){for (int i = n/2-1; i >= 0; i--) // 采用自底向上的方式构造堆 heapAdjust(a, i, n);for (int i = n-1; i > 0; i--){ swap(a[0], a[i]); heapAdjust(a, 0, i);}}