【数据结构】二叉树顺序结构及实现(一)

简介: 【数据结构】二叉树顺序结构及实现(一)

前言


 在前面的学习中,我们实现了栈与队列的实现。今天我们就通过顺序表来实现二叉树!


a004f90e77cc5b5c625c6fd2b3684e42_1304f5049c4f4a408a4df6230bf1cde5.png


一. 二叉树的顺序结构


我们如何让顺序表和二叉树建立联系呢?


我们可以先对二叉树的每个结点进行编号,通过数组的连续排列建立以下联系:


5f83a0c7ebcc85aa0cdf4953d2caeab2_be49312fb955419db247f7bc0fb63da4.png


这样我们就可以通过数组的下标来模拟实现二叉树了!


5f83a0c7ebcc85aa0cdf4953d2caeab2_be49312fb955419db247f7bc0fb63da4.png


但是普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。


cde7747ff8a2144d593b8f607fae43b0_18b40ce79f1347b8b84630a6bb98756d.png


所以我们的数组存储表示二叉树只适合完全二叉树。


二.堆的概念及结构


b1908d8d19bc5ba3453010ffe35f6ed7_d0fe48ae29b94f44a331bd4bc03821a7.png


简单的来说,堆就是一颗完全二叉树,并且有以下性质:


堆中某个节点的值总是不大于或不小于其父节点的值;

堆总是一棵完全二叉树。

其中分为小根堆和大根堆:


小根堆:

树中所有父亲都小于等于孩子:


f6d2401f676bec91fd353776e9b4209f_f89d367936324d10b7330b3fbc619dfb.png


大根堆:

树中所有父亲都大于等于孩子


6b213da452199673d16be32262766886_b2140a0239354853b310ba2312b19d0d.png


注意:

在数据结构里面我们所学的栈,堆都是一种数据结构,他们与操作系统

中的栈和堆是两回事,一个是数据结构,一个是操作系统相关的知识,一定不要搞混淆!


三.堆的实现:


typedef int HPDataType;
typedef struct Heap
{
  HPDataType* a;
  int size;
  int capacity;
}HP;
void HeapInit(HP* php);
void HeapDestroy(HP* php);
void HeapPush(HP* php, HPDataType x);
void HeapPop(HP* php);
HPDataType HeapTop(HP* php);
bool HeapEmpty(HP* php);
int HeapSize(HP* php);
void AdjustUp(HPDataType* a, int child);
void AdjustDown(HPDataType* a, int n, int parent);




1.堆的插入(向上调整算法):


 先插入一个数到数组的尾上,再进行向上调整算法,直到满足堆。


向上调整算法的条件是:

除了child结点,之前的结点都是堆


e45e8f8f926f40994c38127d9d70b3d5_ad740e4e1f904fb9ad8b531e1b8043e4.png


代码实现:


void AdjustUp(HPDataType* a, int child)
{
  int parent = (child - 1) / 2;
  while (child>0)
  {
  if (a[child] > a[parent])
  {
    swap(&a[child],&a[parent]);
    child = parent;
    parent = (child - 1) / 2;
  }
  else
  {
    break;
  }
  }
}
void HeapPush(HP* php, HPDataType x)
{
  assert(php);
  if (php->capacity == php->size)
  {
  HPDataType* ptr = (HPDataType*)realloc(php->a, sizeof(HPDataType) * php->capacity * 2);
  if (ptr == NULL)
  {
    perror("realloc::fail");
    return;
  }
  php->a = ptr;
  php->capacity *= 2;
  }
  php->a[php->size] = x;
  php->size++;
  AdjustUp(php->a, php->size-1);
}



2.堆的删除(向下调整算法):


 在这里删除堆是指删除堆顶的数据,因为删除堆尾元素没有什么实际的意义。将堆顶的数据与最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。


向下调整算法的条件是:


左右子树都为堆!


df61abfd9fdb0fbfec32b6e4cbe12961_0ae7df0eef554abdaece48964d9b6ad9.png


代码实现:


void HeapPop(HP* php)
{
  assert(php);
  assert(!HeapEmpty(php));
  // 删除数据
  Swap(&php->a[0], &php->a[php->size - 1]);
  php->size--;
  AdjustDown(php->a, php->size, 0);
}
void AdjustDown(HPDataType* a, int n, int parent)
{
  int 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;
  }
  }
}



3.堆的构建:


这里建议把后面的堆排序看了在来看这段代码:


void HeapInitArray(HP* php, int* a, int n)
{
  assert(php);
  php->a = (HPDataType*)malloc(sizeof(HPDataType) * n);
  if (php->a == NULL)
  {
  perror("malloc fail");
  return;
  }
  php->size = n;
  php->capacity = n;
  // 建堆
  for (int i = (n-2)/2; i >= 0; --i)
  {
  AdjustDown(php->a, php->size, i);
  }
}



这里的意思是给你一个属数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。

目录
相关文章
|
27天前
|
存储 机器学习/深度学习
【数据结构】二叉树全攻略,从实现到应用详解
本文介绍了树形结构及其重要类型——二叉树。树由若干节点组成,具有层次关系。二叉树每个节点最多有两个子树,分为左子树和右子树。文中详细描述了二叉树的不同类型,如完全二叉树、满二叉树、平衡二叉树及搜索二叉树,并阐述了二叉树的基本性质与存储方式。此外,还介绍了二叉树的实现方法,包括节点定义、遍历方式(前序、中序、后序、层序遍历),并提供了多个示例代码,帮助理解二叉树的基本操作。
42 13
【数据结构】二叉树全攻略,从实现到应用详解
|
24天前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
24天前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
24天前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
2月前
|
算法
【初阶数据结构篇】二叉树算法题
二叉树是否对称,即左右子树是否对称.
|
2月前
|
存储
【初阶数据结构篇】实现链式结构二叉树(二叉链)下篇
要改变root指针的指向,将本来指向根节点的root指针改为空,所以传二级指针(一级指针也可以,只不过在调用完记得把root置为空)。
|
2月前
|
存储 测试技术
【初阶数据结构篇】实现链式结构二叉树(二叉链)上篇
先构建根结点,再对左右子树构建,每次需要时申请一个结点空间即可,否则返回空指针。
|
2月前
|
存储 算法 测试技术
【初阶数据结构篇】实现顺序结构二叉树(堆的实现方法)
注意传过去的参数是插入的位置,即插入前的size,在调整完后再将size++
|
3天前
|
算法 安全 测试技术
golang 栈数据结构的实现和应用
本文详细介绍了“栈”这一数据结构的特点,并用Golang实现栈。栈是一种FILO(First In Last Out,即先进后出或后进先出)的数据结构。文章展示了如何用slice和链表来实现栈,并通过golang benchmark测试了二者的性能差异。此外,还提供了几个使用栈结构解决的实际算法问题示例,如有效的括号匹配等。
golang 栈数据结构的实现和应用
01_设计一个有getMin功能的栈
01_设计一个有getMin功能的栈