赞
踩
一、树
1.1 树的概念与结构
1.2 树的相关术语
1.3 树的表示
二、二叉树
2.1 二叉树的概念与结构
2.2特殊的二叉树
2.3 二叉树的存储结构
三、实现顺序结构二叉树
3.1 堆的概念与结构
3.2 堆的实现
Heap.h
Heap.c
默认初始化堆
堆的销毁
堆的插入
删除堆顶数据
树形结构中,⼦树之间不能有交集,否则就不是树形结构
孩⼦兄弟表⽰法:
- struct TreeNode
- {
- struct Node* child; // 左边开始的第⼀个孩⼦结点
- struct Node* brother; // 指向其右边的下⼀个兄弟结点
- int data; // 结点中的数据域
- };
⼀个⼆叉树,如果每⼀个层的结点数都达到最⼤值,则这个⼆叉树就是满⼆叉树。也就是说,如果⼀个⼆叉树的层数为 K ,且结点总数是 2 k − 1 ,则它就是满⼆叉树。
完全⼆叉树是效率很⾼的数据结构,完全⼆叉树是由满⼆叉树⽽引出来的。对于深度为 K 的,有 n 个结点的⼆叉树,当且仅当其每⼀个结点都与深度为K的满⼆叉树中编号从 1 ⾄ n 的结点⼀⼀对应时称之为完全⼆叉树。要注意的是满⼆叉树是⼀种特殊的完全⼆叉树。
(假设二叉树层次为 k ,除了第 k 层外,每层结点的个数达到最大结点数,第 k 层结点个数不一定达到最大结点数)
小根堆 大根堆
以小根堆为例子:
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<stdbool.h>
-
- //定义堆的结构---数组
-
- typedef int HPDataType;
-
- typedef struct Heap
- {
- HPDataType* arr;
- int size;//有效的数据个数
- int capacity;//空间大小
- }HP;
-
- //初始化
- void HPInit(HP* php);
-
- //销毁
- void HPDestroy(HP* php);
-
- //堆的插入
- void HPPush(HP* php, HPDataType x);
-
- //出堆,删除堆顶数据
- void HPPop(HP* php);
-
- //返回堆顶数据
- HPDataType HPTop(HP* php);
-
- // 判空
- bool HPEmpty(HP* php);
- void HPInit(HP* php)
- {
- assert(php);
- php->arr = NULL;
- php->capacity = php->size = 0;
- }
- void HPDestroy(HP* php)
- {
- assert(php);
- if (php->arr)
- {
- free(php->arr);
- php->arr = NULL;
-
- php->capacity = php->size - 0;
- }
- }
如果要在下一个数据 “50” 到 arr【6】的位置上就不满足小堆的特性,
此时我们就要用到:堆的向上调整算法
- void swap(int* x, int* y)
- {
- int z = *x;
- *x = *y;
- *y = z;
- }
-
- void Adjustup(HPDataType* arr, int child)
- {
- int parent = (child - 1) / 2;
-
- while (child > 0)
- {
- if (arr[child] < arr[parent]) //如果插入的数据大小小于他的父节点
- {
- swap(&arr[child], &arr[parent]); //交换
- child = parent; //交换后的孩结点来到原来他的父节点的位置
- parent = 2 * child - 1;
- }
- else
- {
- break;
- }
- }
- }
-
- void HPPush(HP* php, HPDataType x)
- {
- assert(php);
-
- //判断空间是否足够
- if (php->size == php->capacity)
- {
- //扩容
- int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
- HPDataType* tmp = (HPDataType*)realloc(php->arr, newcapacity * sizeof(HPDataType));
-
- if (tmp == NULL)
- {
- perror("realloc fail!");
- exit(1);
- }
- php->arr = tmp;
- php->capacity = newcapacity;
- }
- php->arr[php->size] = x;
- php->size++;
-
- Adjustup(php->arr, php->size - 1);
- }
如果直接删除 arr【0】,就会改变原先堆的结构,所以我么可以先先将头和尾的数据交换,在删除 arr【5】,但是又有问题出现。交换删除后的数据有可能不满足小堆的特性,此时就要用到:堆的向下调整算法
- void AdjustDown(HPDataType* arr, int parent, int n)
- {
- int child = parent * 2 + 1; //左孩子
-
- while (child < n) //这里注意循环的条件
- {
- //找左右孩子中找最小的
- if (child + 1 < n && arr[child] > arr[child + 1])
- {
- child++;
- }
- if (arr[child] < arr[parent])
- {
- swap(&arr[child], &arr[parent]);
- parent = child;
- child = parent * 2 + 1;
-
- }
- else
- {
- break;
- }
- }
- }
-
- void HPPop(HP* php)
- {
- assert(php && php->size);
-
- //arr[0] arr[size-1]
- swap(&php->arr[0], &php->arr[php->size - 1]);
-
- php->size--;
-
- AdjustDown(php->arr, 0, php->size);
-
-
- }
最后测试一下代码的实现
- #include"Heap.h"
-
- void Hptest()
- {
- HP hp;
- HPInit(&hp);
-
- int arr[] = { 17,25,60,54,30,70 };
-
- for (int i = 0; i < 6; i++)
- {
- HPPush(&hp, arr[i]);
- }
-
- HPPop(&hp);
- }
-
-
- int main()
- {
- Hptest();
- return 0;
- }
方法一:基于已有数组建堆、取堆顶元素完成排序版本
- // 1、需要堆的数据结构
- // 2、空间复杂度 O(N)
- void HeapSort(int* a, int n)
- {
- HP hp;
- for(int i = 0; i < n; i++)
- {
- HPPush(&hp,a[i]);
- }
- int i = 0;
- while (!HPEmpty(&hp))
- {
- a[i++] = HPTop(&hp);
- HPPop(&hp);
- }
- HPDestroy(&hp);
- }
方法二:
- // 升序,建⼤堆
- // 降序,建⼩堆
- // O(N*logN)
- void HeapSort(int* a, int n)
- {
- // a数组直接建堆 O(N)
- for (int i = (n-1-1)/2; i >= 0; --i)
- {
- AdjustDown(a, n, i);
- }
-
- // O(N*logN)
- int end = n - 1;
- while (end > 0)
- {
- Swap(&a[0], &a[end]);
- AdjustDown(a, end, 0);
- --end;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。