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

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

前言


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


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);
  }
}



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

目录
相关文章
|
1月前
|
机器学习/深度学习 存储 算法
数据结构实验之二叉树实验基础
本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
81 4
|
1月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
78 16
|
1月前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
131 8
|
2月前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
31 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
2月前
|
存储 算法 搜索推荐
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
这篇文章主要介绍了顺序存储二叉树和线索化二叉树的概念、特点、实现方式以及应用场景。
35 0
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
|
2月前
|
Java
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
31 1
|
2月前
|
算法 Java C语言
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(一)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(一)
29 1
|
2月前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
2月前
探索顺序结构:栈的实现方式
探索顺序结构:栈的实现方式
|
2月前
|
存储 算法
数据结构与算法学习十六:树的知识、二叉树、二叉树的遍历(前序、中序、后序、层次)、二叉树的查找(前序、中序、后序、层次)、二叉树的删除
这篇文章主要介绍了树和二叉树的基础知识,包括树的存储方式、二叉树的定义、遍历方法(前序、中序、后序、层次遍历),以及二叉树的查找和删除操作。
31 0