选择排序
简单选择排序
区别冒泡排序:
- 不是相邻两两对比交换
- 中途过程中不需要进行交换
简单选择排序算法
void SelectSort(Sqlist &K)
{
for(i=1;i<L.length;++i)
{
k=i;
for(j=i+1;j<=L.length;j++)
if(L.r[j].key<L.r[k].key)
k=j; //记录最小值位置
if(k!=j)
L.r[i]与L.r[k]交换
}
}
复杂度
- 比较次数:无论待排序序列处于什么状态,选择排序所需进行的比较次数都是相同的。
- n/2*(n-1)
- 简单选择排序是不稳定排序
堆排序
定义:若干元素序列 若 i上值小于等于2i 且 小于等于2i+1,则为小根堆;若大于等于,则为大根堆。
堆的实质是一个完全二叉树,二叉树中任意非叶子结点均小于(大于)它的孩子结点。
eg:
{98,77,35,62,55,14,35,48}
是一个大根堆!
堆排序:若在输出堆顶的最小值(最大值)后,使得剩余n-1个元素的序列重建成一个堆,则得到n个元素的次小值(次大值),反复,便能得到一个有序序列。
如何在输出堆顶元素后,调整剩余元素为一个新堆?
以小根堆为例:
- 输出堆顶元素后,以堆顶元素最后一个元素替代之;(一层一层的来)
- 然后将根结点值与左右子树的根结点值比较,并于其中小者进行交换;
- 重复上述步骤,直至叶子结点,将得到新的堆,称这个从堆顶到叶子的调整过程为”筛选“
如何由一个无序序列建成一个堆?
由于堆的实质,是一个线性表,用顺序存储一个堆。
方法:
- 从最后一个非叶子结点开始,即从第 n/2 个元素开始,将以该元素为根的二叉树调整为堆
- 将以序号为n/2-1的结点为根的二叉树调整为堆
- 再将以序号为n/2-2的结点为根的二叉树调整为堆
- 再将以序号为n/2-3的结点为根的二叉树调整为堆,调整到1号位置为止。
PS:如果双亲为3 则孩子结点位置为 6 and 7 (2i and 2i +1)
for(i=n/2;i>=i;i--)
HeapAdjust(R,i,n);
实质上,堆排序就是利用完全二叉树中父节结点和孩子结点之间的内在关系来排序的。
堆排序算法:
小结:
- 堆排序仅需要一个记录大小供交换用的辅助存储空间。
- 堆排序是一种不稳定的排序方法,它不适用于待排序记录个数n较少的情况,但对n较大的文件还是很有效的。