目次
媒介
一、堆的实现
1.1 头文件
1.2 堆的初始化及销毁
1.3 堆的插入
1.4 堆的删除
1.5 取堆顶数据和判空
媒介
前面我们讲了二叉树有顺序结构和链式结构,今天就来讲一下顺序结构
普通的二叉树是不适当用数组来存储的,由于可能会存在大量的空间浪费。而完全二叉树更适当利用顺序结 构存储。现实中我们通常把堆(一种二叉树)利用顺序结构的数组来存储,必要留意的是这里的堆和操作系统 假造进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。
一、堆的实现
堆的性质: 堆中某个结点的值总是不大于或不小于其父结点的值,堆总是一棵完全二叉树。
1.1 头文件
- #include<stdio.h>
- #include<assert.h>
- #include<stdlib.h>
- #include<stdbool.h>
- typedef int HPDataType;
- typedef struct Heap
- {
- HPDataType* a;
- int size;
- int capacity;
- }Heap;
- //堆的初始化
- void HeapInit(Heap*hp);
- // 堆的销毁
- void HeapDestory(Heap* hp);
- // 堆的插入
- void HeapPush(Heap* hp, HPDataType x);
- // 堆的删除
- void HeapPop(Heap* hp);
- // 取堆顶的数据
- HPDataType HeapTop(Heap* hp);
- // 堆的判空
- bool HeapEmpty(Heap* hp);
复制代码 写入我们必要用到的头文件以及堆的底子结构另有用到的堆的功能函数名。
1.2 堆的初始化及销毁
- void HeapInit(Heap* hp)
- {
- assert(hp);
- hp->a = NULL;
- hp->size = hp->capacity = 0;
- }
- void HeapDestory(Heap* hp)
- {
- assert(hp);
- free(hp->a);
- hp->a = NULL;
- hp->size = hp->capacity = 0;
- }
复制代码 这个没什么还说的,就是把数据都置空了。
1.3 堆的插入
- void HeapPush(Heap* hp, HPDataType x)
- {
- assert(hp);
- if (hp->size == hp->capacity)
- {
- int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
- HPDataType* tem = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * newcapacity);
- hp->capacity = newcapacity;
- hp->a = tem;
- }
- hp->a[hp->size] = x;
- hp->size++;
- adjustup(hp->a, hp->size-1);
- }
复制代码 这里我们会用到向上调整算法
- void swap(HPDataType* a, HPDataType* b)
- {
- HPDataType tem = *a;
- *a = *b;
- *b = tem;
- }
- void adjustup(HPDataType* a, HPDataType child)
- {
- int parent = (child - 1) / 2;
- while (child > 0)
- {
- if (a[parent] > a[child])
- {
- swap(&a[parent], &a[child]);
- child = parent;
- parent = (child - 1) / 2;
- }
- else
- {
- break;
- }
- }
- }
复制代码 插入数据后要保持父节点比子节点小的性质,要把数据一步步向上调整。
1.4 堆的删除
- void HeapPop(Heap* hp)
- {
- assert(hp);
- swap(&hp->a[0], &hp->a[hp->size - 1]);
- hp->size--;
- adjustdown(hp->a, hp->size,0);
- }
复制代码
删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。
- void adjustdown(HPDataType* a, HPDataType n,HPDataType parent)
- {
- HPDataType child = parent * 2 + 1;
- while (child < n)
- {
- if (child + 1 < n && a[child + 1] < a[child])
- {
- child++;
- }
- if (a[child] < a[parent])
- {
- swap(&a[child], &a[parent]);
- parent = child;
- child = parent * 2 + 1;
- }
- else
- {
- break;
- }
- }
- }
复制代码 这里给个例子:
现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根结点开始的向下调整算法可以把它调整 成一个小堆。向下调整算法有一个条件:左右子树必须是一个堆,才能调整。
int array[] = {27,15,19,18,28,34,65,49,25,37};
1.5 取堆顶数据和判空
- HPDataType HeapTop(Heap* hp)
- {
- return hp->a[0];
- }
复制代码 由于是基于数组写的,以是取堆顶就很简朴了。
- bool HeapEmpty(Heap* hp)
- {
- return hp->size == 0;
- }
复制代码 假如数据位空了,那么堆就是空的。
二、完备源码
dui.h
- #include<stdio.h>
- #include<assert.h>
- #include<stdlib.h>
- #include<stdbool.h>
- typedef int HPDataType;
- typedef struct Heap
- {
- HPDataType* a;
- int size;
- int capacity;
- }Heap;
- void HeapInit(Heap*hp);
- void HeapDestory(Heap* hp);
- void HeapPush(Heap* hp, HPDataType x);
- void HeapPop(Heap* hp);
- HPDataType HeapTop(Heap* hp);
- int HeapSize(Heap* hp);
- bool HeapEmpty(Heap* hp);
复制代码 dui.c
- #include"dui.h"void HeapInit(Heap* hp)
- {
- assert(hp);
- hp->a = NULL;
- hp->size = hp->capacity = 0;
- }
- void HeapDestory(Heap* hp)
- {
- assert(hp);
- free(hp->a);
- hp->a = NULL;
- hp->size = hp->capacity = 0;
- }void swap(HPDataType* a, HPDataType* b)
- {
- HPDataType tem = *a;
- *a = *b;
- *b = tem;
- }
- void adjustup(HPDataType* a, HPDataType child)
- {
- int parent = (child - 1) / 2;
- while (child > 0)
- {
- if (a[parent] > a[child])
- {
- swap(&a[parent], &a[child]);
- child = parent;
- parent = (child - 1) / 2;
- }
- else
- {
- break;
- }
- }
- }void HeapPush(Heap* hp, HPDataType x)
- {
- assert(hp);
- if (hp->size == hp->capacity)
- {
- int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
- HPDataType* tem = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * newcapacity);
- hp->capacity = newcapacity;
- hp->a = tem;
- }
- hp->a[hp->size] = x;
- hp->size++;
- adjustup(hp->a, hp->size-1);
- }void adjustdown(HPDataType* a, HPDataType n,HPDataType parent)
- {
- HPDataType child = parent * 2 + 1;
- while (child < n)
- {
- if (child + 1 < n && a[child + 1] < a[child])
- {
- child++;
- }
- if (a[child] < a[parent])
- {
- swap(&a[child], &a[parent]);
- parent = child;
- child = parent * 2 + 1;
- }
- else
- {
- break;
- }
- }
- }void HeapPop(Heap* hp)
- {
- assert(hp);
- swap(&hp->a[0], &hp->a[hp->size - 1]);
- hp->size--;
- adjustdown(hp->a, hp->size,0);
- }HPDataType HeapTop(Heap* hp)
- {
- return hp->a[0];
- }int HeapSize(Heap* hp){ return hp->size;}bool HeapEmpty(Heap* hp)
- {
- return hp->size == 0;
- }
复制代码
还是要本身动手写一边才能有印象,写完每个功能点最好一个一个的去测试,这样就不会那么麻烦,更容易知道错哪了,全部写写完再测试,没错误还好说,有错的话,找起来会很痛楚的。
本篇内容就到这里了,盼望对各位有资助,假如有错误欢迎指出。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |