温故而知新 -> 数据结构 -> 二叉树 -> 顺序存储 ->程序实现1_利用结构体

温故而知新 -> 数据结构 -> 二叉树 -> 顺序存储 ->程序实现1_利用结构体

本篇博客是基于 温故而知新 -> 数据结构 ->树 -> 二叉树 -> 顺序存储 中实现堆顺序存储 的理论知识进行程序实现!

其中实现了 堆 的 (入堆)(出堆)(堆顶元素)改(没写(~ ̄▽ ̄)~),判空,打印等操作!并附带了相关实例以及对应的运行结果!

注意:其中代码有很大冗余,且未考虑性能最优,读者有兴趣可进一步精简!

具体内容如下:
(1)newHeap.h

#ifndef __NEWHEAP_H_
#define __NEWHEAP_H_

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

typedef int HDataType;
typedef struct heap
{
	HDataType *_data;
	int _size;
	int _capacity;
}heap;

#endif

(2)main.c


#include"newHeap.h"

void Swap(int *a, int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
}

//堆的初始化
void heapInit(heap *hp)
{
	if (hp == NULL)
		return;
	hp->_data = NULL;
	hp->_size = hp->_capacity = 0;
}

//堆是否为空
int heapEmpty(heap *hp)
{
	if (hp == NULL || hp->_size == 0)
		return 1;
	else
		return 0;
}

/*向下调整  小堆 */
void shiftDown(int *arr, int n, int curPos)
{
	//printf("%d ", arr[1]);
	//左孩子
	int child = 2 * curPos + 1;
	while (child < n)
	{
		//从左右孩子中找到一个最小值的位置
		if (((child + 1) < n) && (arr[child + 1] < arr[child]))
			++child;//和右孩子进行交换
		//需要调整的数据和最小值进行比较,若小于最小值,则不需要交换,反之需要交换
		if (arr[child] < arr[curPos])
		{
			int t = arr[curPos];
			arr[curPos] = arr[child];
			arr[child] = t;

			//更新当前位置
			curPos = child;
			child = 2 * curPos + 1;
		}
		else
			break;
	}

}

/*大堆  */
//void shiftDown(int *arr, int n, int curPos)
//{
//	//printf("%d ", arr[1]);
//	//左孩子
//	int child = 2 * curPos + 1;
//	while (child < n)
//	{
//		//从左右孩子中找到一个最小值的位置
//		if (((child + 1) < n) && (arr[child + 1] > arr[child]))
//			++child;//和右孩子进行交换
//		//需要调整的数据和最小值进行比较,若小于最小值,则不需要交换,反之需要交换
//		if (arr[child] > arr[curPos])
//		{
//			int t = arr[curPos];
//			arr[curPos] = arr[child];
//			arr[child] = t;
//
//			//更新当前位置
//			curPos = child;
//			child = 2 * curPos + 1;
//		}
//		else
//			break;
//
//	}
//
//}

/*向上调整  小堆*/
void shiftUp(int *arr, int n, int curPos)
{
	//父节点位置
	int parent = (curPos - 1) / 2;
	while (curPos > 0)
	{
		//比较当前位置和父节点
		if (arr[curPos] < arr[parent])
		{
			int t = arr[curPos];
			arr[curPos] = arr[parent];
			arr[parent] = t;

			//交换结束后,更新当前位置,继续往上走
			curPos = parent;
			parent = (curPos - 1) / 2;
		}
		else
			break;//结束调整
	}


}

/* 大堆  */
//void shiftUp(int *arr, int n, int curPos)
//{
//	//父节点位置
//	int parent = (curPos - 1) / 2;
//	while (curPos > 0)
//	{
//		//比较当前位置和父节点
//		if (arr[curPos] > arr[parent])
//		{
//			int t = arr[curPos];
//			arr[curPos] = arr[parent];
//			arr[parent] = t;
//
//			//交换结束后,更新当前位置,继续往上走
//			curPos = parent;
//			parent = (curPos - 1) / 2;
//		}
//		else
//			break;//结束调整
//	}
//
//}

void checkCapacity(heap *hp)
{
	if (hp->_size == hp->_capacity)
	{
		hp->_capacity = hp->_capacity == 0 ? 1 : 2 * hp->_capacity;
		hp->_data = (HDataType*)realloc(hp->_data, sizeof(HDataType)*hp->_capacity);
	}
}

//堆的插入
void heapPush(heap *hp, HDataType val)
{
	//检查容量
	checkCapacity(hp);
	//尾插
	hp->_data[hp->_size++] = val;
	//向上调整  从最后一个位置开始往上   从0开始计数
	shiftUp(hp->_data, hp->_size, hp->_size - 1);

	//hp->_data[hp->_size] = val;
	//shiftUp(hp->_data, hp->_size+1, hp->_size);
	//hp->_size++;
}

//堆的删除:删除堆顶元素  首尾交换,删除原堆顶(现堆尾)元素,然后向下调整
void heapPop(heap *hp)
{
	if (hp == NULL || hp->_size == 0)
		return;
	//首尾交换交换
	Swap(&hp->_data[0], &hp->_data[hp->_size - 1]);
	//尾删
	hp->_size--;
	//向下调整
	shiftDown(hp->_data, hp->_size, 0);
}

//获取堆顶元素
HDataType heapTop(heap *hp)
{
	return hp->_data[0];
}

//建堆
void creatHeap(int *arr, int n)
{
	//从最后一个非叶子节点进行向下调整
	for (int i = (n - 2) / 2; i >= 0; --i)
	{
		shiftDown(arr, n, i);
	}
}
void heapPrint(heap *hp)
{
	printf("堆中内容:");
	for (int i = 0; i < hp->_size; i++)
		printf("%d ", hp->_data[i]);
	printf("\n");
}

//堆的排序
void test()
{
	//用小堆的向下调整法,实现的结果是倒序排列,由大到小
	//用大堆的向下调整法,实现的结果是正序排列,由小到大

	//int arr[] = { 20, 17, 4, 16, 5, 3 };
	//int n = sizeof(arr) / sizeof(arr[0]);
	建堆 (n - 2) / 2 此为最后一个非叶子节点的位置
	//for (int i = (n - 2) / 2; i >= 0; --i)
	//{
	//	shiftDown(arr, n, i);
	//}
	//printArr(arr, n);
	//int end = n - 1;
	//while (end > 0)
	//{
	//	//对的删除过程
	//	Swap(&arr[0], &arr[end]);
	//	shiftDown(arr, end, 0);
	//	printArr(arr, end);
	//	--end;
	//}
	//	hp.HeapPush(66);
	//	hp.HeapPrint();// 66
	//	hp.HeapPush(55);
	//	hp.HeapPrint();// 55 66
	//	hp.HeapPush(22);
	//	hp.HeapPrint();// 22 66 55
	//	hp.HeapPush(44);
	//	hp.HeapPrint();// 22 44 55 66
	//	hp.HeapPush(33);
	//	hp.HeapPrint();// 22 33 55 66 44
	//	hp.HeapPush(11);
	//	hp.HeapPrint();// 11 33 22 66 44 55
	heap hp;
	heapInit(&hp);
	/* 实验插入 */
	heapPush(&hp, 66);
	heapPrint(&hp);//66
	heapPush(&hp, 55);
	heapPrint(&hp);//55 66
	heapPush(&hp, 22);
	heapPrint(&hp);//22 66 55
	heapPush(&hp, 44);
	heapPrint(&hp);//22 44 55 66
	heapPush(&hp, 33);
	heapPrint(&hp);//22 33 55 66 44
	heapPush(&hp, 11);
	heapPrint(&hp);//11 33 22 66 44 55

	/* 实验删除 */
	heapPop(&hp);
	heapPrint(&hp);//22 33 55 66 44
	heapPop(&hp);
	heapPrint(&hp);//33 44 55 66
	heapPop(&hp);
	heapPrint(&hp);//44 66 55
	heapPop(&hp);
	heapPrint(&hp);//55 66
	/* 实验堆顶 */
	printf("此时堆顶元素为:%d \n", heapTop(&hp));
}

int main()
{
	test();

	system("pause");
	return 0;
}

(3)运行结果
在这里插入图片描述

以上就是本篇博客内容!
侵权删~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值