您的位置:首页 > 其它

堆排序的非递归实现

2016-06-12 22:25 267 查看
堆排序中的堆我们指的是二叉堆,具有以下特点
1、是一个完全二叉树。
2、任一个结点值都比子结点大(大根堆),小(小根堆)。
堆排序具有的特点。
1、原地排序,所以其空间复杂度为lg(n)。
2、时间复杂度为nlg(n),而且最坏的情况下也是nlog(n)。
3、堆排序是稳定的。因为我们是基于值大小比较结果,来调整元素的位置的。相同值的元素比较时,不交换位置,与冒泡法一样。

下面介绍其思路。
直接按照C语言的环境下写算法思路,有兴趣的同学可以去Linux源码树中看下lib/sort.c中给出的一个泛型的非递归的实现。我在这里给出同样的算法,更通俗一些。
1、堆的建立。//验证通过.
输入为:一个无序的一组数,存贮在一个一维数组中。
思路:从最后一个数据开始,倒序向前访问各个数组成员,每次访问,对其兄弟节点和父节点进行比较,找出最大值将其交换到父节点的位置上。一共有N个元素,则其叶子结点数量最大为lg(n)
1)由数据数目计算出最后一个叶子结点是否有兄弟节点。

If (num% 2 == 1) //有兄弟结点
比较兄弟节点、该节点、父结点,取最大值与父结点交换。
当前结点序号前移一个
Else
没有兄弟结点,不执行任何操作。
While(当前结点不是第一个节点) {
比较兄弟节点、该节点、父结点,取最大值与父结点交换。
当前结点前移2个。
}
       2) 完成排序,时间复杂度为nlg(n)

已经完成的堆中,堆顶是最大值。步骤如下:
num = 堆长度-1
while(num>=0) {
把堆顶的最大值与堆底部,最右侧的元素交换。
堆长度-1
堆顶的元素不是最大值,沿一条到叶子结点的路径向下渗透。
}
代码如下:

/*************************************************************************
> File Name: heap.c
> Author: lin
> Mail: maolin.1@163.com
> Created Time: 2016年1月1日 星期五 21时10分14秒
************************************************************************/
#include<stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define PARENT(i) ((i+1)/2-1)
int heap_sort(int*, int);
void swap(int*, int*);
 
int main(int argc, char *argv[]) {
int total_num = 10, i;
int array[20] = {59, 32, 8, 23, 9, 5, 12, 10, 100,29 };
int j;
i = 0;
puts("before build");
for (i = 0; i < total_num; i++)
printf("%d ", array[i]);
puts("");
if (!heap_sort(array, total_num)) {
puts("after build");
for (i = 0; i < total_num; i++)
printf("%d ", array[i]);
}
else
puts("failed");
puts("");
}
 
 
 
void swap (int *num1, int *num2) {
int tmp;
tmp = *num1;
*num1 = *num2;
*num2 = tmp;
}
 
int heap_sort(int *array,int num) {
int current_ind = num - 1;
int max_ind = 0, i, j, k;
int heap_size;
//build the heap;
if (num == 0 || num == 1)
{
return 1;
}
if (current_ind % 2 == 1) {
if (array[current_ind] > array[PARENT(current_ind)])
{
swap (&array[current_ind], &array[PARENT(current_ind)]);
}
current_ind--;
}
while (current_ind > 0) {
max_ind = current_ind - 1;
if (array[current_ind] > array[current_ind - 1])
max_ind = current_ind;
if (array[max_ind] > array[PARENT(max_ind)]) {
swap (&array[max_ind], &array[PARENT(current_ind)]);
}
current_ind -= 2;
}
//sort
heap_size = num;
while(heap_size >= 1) {
swap(&array[0],&array[heap_size - 1]);
heap_size--;
for (j = 0; 2 * j + 1 <= heap_size - 1; j = k) {
k = 2 * j + 1;
if (array[k]< array[k + 1] && k + 1 <= heap_size - 1)
k++;
if (array[k] < array[j])
break;
swap(&array[k], &array[j]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: