堆排序实现

一、堆排序简单介绍

1、什么是堆:

堆是一个完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。排序的平均时间复杂度为Ο(nlogn) .

算法演示

2、筛选一个节点:

筛选的目的是通过调整节点之间的key值使得以当前结点为根的子树也是一个堆。

3、堆排序的基本过程:

1、从最后一个非叶子节点(当前待排序节点数/2)开始筛选,筛选到第一个节点结束,此时第一个节点就是当前的最值。

2、将当前最值与最后一个节点交换(即取出最值)。当前待排序节点数-1。

3、在已有的堆的基础上筛选第一个节点(因为此时只有第一个节点不符合堆的特性)。

4、重复步骤2、3直到当前带排序节点数减为1。


二、代码实现

</pre><pre name="code" class="cpp">#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define DATA_SIZE 20

int*  init_data(int *a, int len);
void free_date(int *a);
void print_data(int *a, int len);
void adjust_heap(int *a, int startidx, int len);
void do_sort(int *a, int len);
void swap(int *a, int i, int j);

int main()
{
	int *a;

	a = init_data(a, DATA_SIZE);
	
	if (!a)
	{
		return -1;
	}

	printf("Before sorting:\n");
	print_data(a, DATA_SIZE);

	do_sort(a, DATA_SIZE);

	printf("After sorting:\n");
	print_data(a, DATA_SIZE);

	free_date(a);

	return 0;
}

int* init_data(int *a, int len)
{	
	a = (int*)malloc(len*sizeof(int));
	if (!a)
	{
		return NULL;
	}
	srand(time(NULL));
	
	int i;

	for (i = 0 ; i < len ; ++i)
	{
		a[i] = rand()%100;
	}

	return a;
}

void print_data(int *a, int len)
{
	int i;

	for (i = 0 ; i < len ; ++i)
	{
		printf("%3d", a[i]);
	}

	printf("\n");
}

void free_date(int *a)
{
	free(a);
}

void do_sort(int *a, int len)
{
	int first_no_leaf = len/2 - 1;
	
	int i;

	for (i = first_no_leaf ; i >= 0 ; --i)
	{
		adjust_heap(a, i, len - i);
	}
	
	for (i = len - 1; i > 0 ; --i)
	{
		swap(a, 0, i);
		adjust_heap(a, 0, i);
	}
}

void adjust_heap(int *a, int startidx, int len)
{
	int cur_result = startidx;
	int tmp = a[cur_result];

	while (1)
	{
		int cur_left = 2*cur_result + 1;
		int cur_right = cur_left + 1;

		if (cur_right - startidx >= len)
		{
			if (cur_left - startidx >= len)
			{
				a[cur_result] = tmp;
				break;
			}
			else
			{
				if (tmp < a[cur_left])
				{
					a[cur_result] = a[cur_left];
					cur_result = cur_left;
				}
				else
				{
					break;
				}
			}
		}
		else
		{
			if (a[cur_left] >= a[cur_right])
			{
				if (tmp < a[cur_left])
				{
					a[cur_result] = a[cur_left];
					cur_result = cur_left;
				}
				else
				{
					break;
				}
			}
			else
			{
				if (tmp < a[cur_right])
				{
					a[cur_result] = a[cur_right];
					cur_result = cur_right;
				}
				else
				{
					break;
				}
			}
		}

	}
	a[cur_result] = tmp;
}

void swap(int *a, int i, int j)
{
	int tmp = a[i];
	a[i] = a[j];
	a[j] = tmp;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值