今天介绍一种我刚刚学到的新的数据结构.二叉树 详情如下:
二叉树的概念:二叉树是一种有限节点的集合,也就是说它的节点个数是有限的. 二叉树的分类:二叉树分为 完全二叉树和满二叉树 二叉树的存储结构:顺序存储结构和链式存储结构
这次主要介绍二叉树的顺序存储结构 ,顺序存储结构主要介绍完全二叉树,完全二叉树是按照一维数组的形式进行存储的,因此是非常适合顺序存储这种存储方式的.而堆是完全二叉树的一个具体的应用. 堆又分为:大堆和小堆. 大堆指的是任意双亲节点都大于其左右节点,因此大堆是降序的顺序 堆顶元素最大 小堆指的是任意双亲节点都小于其左右节点,因此小堆是升序的顺序 堆顶元素最小 堆的具体实现代码如下: 首先第一部分我们来新建一个源文件,“heap.h”,在这里我们定义一下堆的结构,以及关于堆的一系列操作函数 代码如下
#pragma once typedef int HPDataType; typedef struct Heap{ HPDataType *_array;//指向一段连续的空间 int _capacity; int _size; } Heap; void InitHeap(Heap*hp,HPDataType*array, int size); void InsertHeap(Heap*hp, HPDataType data); void EraseHeap(Heap*hp); int HeapSize(Heap*hp); int HeapEmpty(Heap*hp); HPDataType HeapTop(Heap*hp); void DestoryHeap(Heap*hp); void TestHeap(); void HeapSort(int *array, int size);第二部分新建一个头文件:"heap,c"这部分我们来具体实现一下堆的函数操作细节 代码如下
if (hp->_size == hp->_capacity){ int newcapacity = hp->_capacity * 2; HPDataType*pTmp = (HPDataType*)malloc(sizeof(HPDataType)*newcapacity); if (NULL == pTmp){ assert(0); return; } //拷贝元素 for (int i = 0; i < hp->_size; ++i){ pTmp[i] = hp->_array[i]; } //释放原空间 free(hp->_array); //更新参数 hp->_array = pTmp; hp->_capacity = newcapacity; } } //初始化堆 void InitHeap(Heap*hp, HPDataType*array, int size){ assert(hp); //开辟空间 hp->_array = (HPDataType*)malloc(sizeof(HPDataType)*size); if (hp->_array == NULL){ assert(0); return; } hp->_capacity = size; //将数组中的元素搬移到堆中 for (int i = 0; i < size; ++i){ hp->_array[i] = array[i]; } hp->_size = size; // 将该完全二叉树调整使其满足堆的性质 //找完全二叉树中的倒数第一个非叶子节点 int root = ((size - 2) >> 1); for (; root >= 0; --root){ AdjustDown(hp->_array, size, root); } } //向堆中插入元素 void InsertHeap(Heap*hp, HPDataType data){ //先判断是否需要扩容 CheckCapacity(hp); //将元素放入堆中 hp->_array[hp->_size] = data; hp->_size++; //放入之后有可能破坏堆的性质,如果 破坏了则需要调整 AdjustDown(hp->_array, hp->_size, hp->_size - 1); } //删除堆中元素 void EraseHeap(Heap*hp){ if (HeapEmpty(hp)){ return; } //先交换 再删除 再调整 swap(&hp->_array[0], &hp->_array[hp->_size-1]); hp->_size--; AdjustDown(hp->_array, hp->_size, 0); } //获取堆中元素个数 int HeapSize(Heap*hp){ assert(hp); return hp->_size; } //检查堆是否为空 int HeapEmpty(Heap*hp){ assert(hp); return 0 == hp->_size; } //获取堆顶元素 HPDataType HeapTop(Heap*hp){ assert(hp); return hp->_array[0]; } //摧毁堆 void DestoryHeap(Heap*hp){ assert(hp); if (hp->_array){ free(hp->_array); hp->_capacity = 0; hp->_size = 0; } } //测试堆的相关操作函数 void TestHeap(){ Heap hp;//定义一个堆 int array[] = { 2, 3, 8, 0, 9, 1, 7, 4, 6, 5 }; InitHeap(&hp, array, sizeof(array) / sizeof(array[0])); printf("%d ", HeapSize(&hp)); printf("%d ", HeapTop(&hp)); EraseHeap(&hp); printf("%d ", HeapTop(&hp)); InsertHeap(&hp, 0); printf("%d ", HeapTop(&hp)); DestoryHeap(&hp); } //调整数组中元素使其成为堆 void HeapAdjust(int *array, int size, int parent){ int child = parent * 2 + 1; while (child < size){ //找到左右孩子中较大的孩子 if (child + 1 < size && array[child + 1] > array[child]){ child += 1; } //找到了较大的孩子,然后与双亲比较, if (array[child]>array[parent]){ swap(&array[child], &array[parent]); parent = child; child = parent * 2 + 1; } else { return; } } } //利用删除堆中元素的思想,对 堆进行排序 void HeapSort(int *array, int size){ //:建堆-----大堆 // 找到倒数第一个非叶子节点 int root = ((size - 2) >> 1) ; for (; root >= 0 ;--root){ HeapAdjust(array, size, root); } //2.排序:用堆删除的思想 int end = size - 1; while (end){ swap(&array[0],&array[end]); HeapAdjust(array, end, 0); end--; } } //测试堆的排序情况 void testheap(){ int array[] = { 2, 3, 8, 0, 9, 1, 7, 4, 6, 5 }; HeapSort( array, sizeof(array) / sizeof(array[0])); }第三部分,创建一个头文件:“test.c” 在此定义函数的入口main函数 代码如下:
#include"heap.h" #include<stdio.h> #include<stdlib.h> int main(){ //TestHeap(); testheap(); system("pause"); return 0; }.