堆的增删改查和堆排序(堆是特殊的完全二叉树,堆按顺序表存储)

堆的增删改查和堆排序(堆是特殊的完全二叉树,堆按顺序表存储)

1.堆是特殊的完全二叉树,堆按顺序表存储

2.按下标:叶子结点个数 (n+1)/2 非叶子节点 n/2
按元素:叶子结点个数 (n-1)/2 非叶子节点 n/2-1 父情节点
代码实现

Heap.h

#ifndef _HEAP_H_
#define _HEAP_H_

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

typedef int HPDataType;

typedef struct Heap
{
	HPDataType* data;
	int size;
	int capacity;
}Heap;

void adjustDown(Heap* hp, int n);
void HeapInit(Heap* hp, HPDataType* a, int n);
void HeapDestory(Heap* hp);
void HeapPush(Heap* hp, HPDataType x);
void HeapPop(Heap* hp);
HPDataType HeapTop(Heap* hp);
int HeapSize(Heap* hp);
int HeapEmpty(Heap* hp);//判空
void HeapPrint(Heap* hp);
void HeapPrintS(Heap* hp);
void HeapSort(Heap* hp);// 堆排序

#endif // !_HEAP_H_

Heap.c

#include "Heap.h"

//向下调整算法复杂度O(logn);
void adjustDown(Heap* hp, int cur) {
	assert(hp);
	int n;
	while (cur * 2 + 1 < hp->size) {
		if (cur * 2 + 2 >= hp->size) {
			n = cur * 2 + 1;
		}
		else {
			if (hp->data[cur * 2 + 1] > hp->data[cur * 2 + 2]) {
				n = cur * 2 + 1;
			}
			else {
				n = cur * 2 + 2;
			}
		}
		if (hp->data[cur] < hp->data[n]) {
			int tmp = hp->data[cur];
			hp->data[cur] = hp->data[n];
			hp->data[n] = tmp;
			cur = n;
		}
		else {
			break;
		}
	}
}

//初始堆时间复杂度O(nlogn);
void HeapInit(Heap* hp, HPDataType* a, int n) {
	assert(hp && a);
	hp->capacity = n * 2;
	hp->size = n;
	hp->data = (HPDataType*)calloc(hp->capacity, sizeof(HPDataType));
	for (int i = 0; i < n; i++) {
		hp->data[i] = a[i];
	}
	for (int i = n / 2 - 1; i >= 0; i--) {
		adjustDown(hp, i);
	}
}

void HeapDestory(Heap* hp) {
	assert(hp);
	if (hp->data) {
	}
	free(hp->data);
	hp->data = NULL;
	hp->capacity = 0;
	hp->size = 0;
}

//插入用向上调整算法
void HeapPush(Heap* hp, HPDataType x) {
	assert(hp);
	if (hp->size == hp->capacity) {
		hp->capacity *= 2;
		hp->data = (HPDataType*)realloc(hp->data, hp->capacity*sizeof(HPDataType));
	}
	int cur = hp->size;
	hp->data[hp->size] = x;
	hp->size++;
	while (cur>0) {
		if (hp->data[(cur - 1) / 2] < hp->data[cur]) {
			int tmp = hp->data[(cur - 1) / 2];
			hp->data[(cur - 1) / 2] = hp->data[cur];
			hp->data[cur] = tmp;
			cur = (cur - 1) / 2;
		}
		else {
			break;
		}
	}
}

//删堆顶元素时间复杂度O(longn);
void HeapPop(Heap* hp) {
	assert(hp);
	if (hp->size == 0) {
		return;
	}
	hp->size--;
	int tmp = hp->data[0];
	hp->data[0] = hp->data[hp->size];
	hp->data[hp->size] = tmp;
	adjustDown(hp, 0);
}

HPDataType HeapTop(Heap* hp) {
	assert(hp);
	if (hp->size == 0) {
		return (HPDataType)0;
	}
	return hp->data[0];
}

int HeapSize(Heap* hp) {
	assert(hp);
	return hp->size;
}

//判空
int HeapEmpty(Heap* hp) {
	assert(hp);
	return hp->size == 0;
}

void HeapPrint(Heap* hp) {
	putchar('\n');
	assert(hp);
	int rn = 0;
	for (int i = 0; i < hp->size; i++) {
		printf("%d ", hp->data[i]);
		if (i == rn) {
			putchar('\n');
			rn = 2 * i + 2;
		}
	}
	putchar('\n');
}

void HeapPrintS(Heap* hp) {
	assert(hp);
	for (int i = hp->size - 1; i >=0 ; i--) {
		printf("%d ", hp->data[i]);
		}
}

// 堆排序时间复杂度O(logn);
void HeapSort(Heap* hp) {
	assert(hp);
	int tmp = hp->size;
	while (hp->size > 1) {
		HeapPop(hp);
	}
	hp->size = tmp;
	
}

main.c

#include "Heap.h"

int main() {
	int data[10] = { 29, 72, 48, 53, 45, 30, 18, 36, 13, 35 };
	Heap hp;
	HeapInit(&hp, data, 10);
	HeapPrint(&hp);
	HeapPop(&hp);
	HeapPrint(&hp);
	HeapPop(&hp);
	HeapPrint(&hp);
	HeapPop(&hp);
	HeapPrint(&hp);
	HeapPop(&hp);
	HeapPrint(&hp);
	HeapPop(&hp); 
	HeapPrint(&hp);
	HeapPop(&hp);
	HeapPrint(&hp);
	HeapPop(&hp);
	HeapPrint(&hp);
	HeapPrint(&hp);
	adjustDown(&hp, 0);
	HeapPrint(&hp);
	HeapPush(&hp, 13);
	HeapPush(&hp, 11);
	HeapPrint(&hp);
	HeapPop(&hp, 13);
	HeapPrint(&hp);
	HeapInit(&hp, data, 10);
	HeapPrint(&hp);
	HeapSort(&hp);
	HeapPrintS(&hp);
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值