堆排序(heapsort)

堆的性质

堆排序的时间复杂度是O(n lgn) ,使用一种称之为“堆”的数据结构来进行信息管理。堆不仅在堆排序中,也可以构造一种有效的优先队列。

堆是一个数组,它可以看成一棵完全二叉树。树上的每个结点对应数组中的一个元素。除了最底层外,保证树是完满的,而且是从左向右填充的。

二叉堆分为两种形式:最大堆最小堆

在最大堆中,最大堆的性质是指除了根结点以外的所有结点i都要满足A[parent(i)]>=a[i] 也就是说,每个结点至多与其父结点一样大。因此,堆中的最大的元素存放在根结点中,最小堆与其类似。

维护堆的性质

我们假定需要维护的结点i的左子树与其右子树都是最大堆。这时A[i]可能小于其子结点,这样就违背了最大堆性质。通过让A[i]的值在最大堆中“逐级下降”,使得以下标为i为根结点的子树重新遵循最大堆的性质。

int max_heapify(int i){
    int large = i;
    int l = left(i);
    int r = right(i);

    if(l <= heap_size && heap[large] < heap[l]) large = l;
    if(r <= heap_size && heap[large] < heap[r]) large = r;

    if(large != i){
        int swap = heap[i];
        heap[i] = heap[large];
        heap[large] = swap;

        max_heapify(large);
    }
    return heap[i];
}

建立最大堆

可以利用自底向上的方法,利用过程max_heapify将某一数组转换为最大堆:

int build_max_heap(){
    scanf("%d", &heap_size);
    int init_loop;
    for(init_loop = 1; init_loop <= heap_size; init_loop++) scanf("%d", heap+init_loop);
    int build_loop;
    for(build_loop = heap_size / 2; build_loop >= 1; build_loop--) max_heapify(build_loop);
}

堆排序

	build_max_heap();
	int memory_list_size = heap_size;
	int sort_loop;
	for(sort_loop = memory_list_size; sort_loop >1; sort_loop--){
		int swap = heap[1];
		heap[1] = heap[sort_loop];
		heap[sort_loop] = swap;

		heap_size--;
		max_heapify(1);
	}

优先队列

优先队列是一种用来维护由一组元素构成的集合S的数据结构。其中每一个元素都有一个相关的值,称为关键字

最大优先队列支持一下操作:

插入、返回S中具有最大键字的元素、删除S中最大键字的元素、将元素x关键字增值到k

#include <stdio.h>

#define _MAX_QUEUE_SIZE_ 21

#define _QUEUE_FILL_ERROR_STRING_ "Error, queue filled.\n"
#define _QUEUE_EMPTY_ERROR_STRING_ "Error, queue empty.\n"

int heap[_MAX_QUEUE_SIZE_];
int heap_size;

int father(int i) { return i / 2; }
int left(int i) { return i * 2; }
int right(int i) { return i * 2 + 1; }

void init(){
	heap_size = 0;
}

void insert(int i){
	if(heap_size == _MAX_QUEUE_SIZE_) { printf(_QUEUE_FILL_ERROR_STRING_); return ; }
	heap_size++;
	heap[heap_size] = i;
	int value_pointer = heap_size;
	int f = father(value_pointer);
	while(f != 0 && heap[f] < heap[value_pointer]){
		int swap = heap[f];
		heap[f] = heap[value_pointer];
		heap[value_pointer] = swap;

		value_pointer = f;
		f = father(value_pointer);
	}
}

int maximum() { return heap[1]; }

void max_heapity(int i){
	int large = i;
	int r = right(i);
	int l = left(i);
	
	if(r <= heap_size && heap[r] > heap[large]) large = r;
	if(l <= heap_size && heap[l] > heap[large]) large = l;

	if(large != i){
		int swap = heap[large];
		heap[large] = heap[i];
		heap[i] = swap;

		max_heapity(large);
	}
}

int extract_max(){
	if(heap_size == 0) { printf(_QUEUE_EMPTY_ERROR_STRING_); return ; }
	
	int swap = heap[1];
	heap[1] = heap[heap_size];
	heap[heap_size] = swap;
	
	heap_size--;
	
	if(heap_size != 0) max_heapity(1);
}

void increase_key(int k, int v){
	int old_value = heap[k];
	int new_value = heap[k] + v;
	if(new_value < old_value){
		max_heapity(k);
	}
	else{
		int value_pointer = k;
		int father_pointer = father(value_pointer);
		
		while(father_pointer != 0 && heap[father_pointer] < heap[value_pointer]){
			int swap = heap[father_pointer];
			heap[father_pointer] = heap[value_pointer];
			heap[value_pointer] = swap;

			value_pointer = father_pointer;
			father_pointer = father(value_pointer);
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值