【数据结构与算法】二叉树的综合运用--1

简介: 【数据结构与算法】二叉树的综合运用--1

一,层序遍历算法

       二叉树的层序遍历是一层一层的从左到右遍历,现在问题是二叉树不支持随机访问,因此,我们需要借助其它结构来实现这一功能。通常,对于这种遍历算法我们要借助队结构的概念。


       补充:树的层序遍历也叫做广度优先遍历,而广度优先遍历通常要借助队列的结构实现。


1-1,队列结构的设立

       队列的结构相信大家都已非常熟悉了,如果队列结构不清楚的可以观看本人以前讲解队列的文章,本文在这里就不做过多说明了。我们可定义一个头文件,将队列的基础算法写进去,其中,要注意的是队列中的元素是树中的结点,因为往队列中装数据装的是树的结点,不可直接装树结点的数据,否则设置此结构几乎没用,下文分析时会详细说明,在这里我们只需先构造队列中的基础算法即可。如下:


#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef struct Tree DataType;
typedef struct Node {
  DataType* val;
  struct Node* next;
}Node;
typedef struct Queue {
  Node* head;
  Node* tail;
}Queue;
void QueueInit(Queue* Q) {
  Q->head = Q->tail = 0;
}
void QueuePush(Queue* Q, DataType* x) {
  Node* node = (Node*)malloc(sizeof(Node));
  if (!node) {
  return;
  }
  node->val = x;
  node->next = 0;
  if (!Q->head) {
  Q->head = Q->tail = node;
  }
  else {
  Q->tail->next = node;
  Q->tail = node;
  }
}
void QueuePop(Queue* Q) {
  if (!Q->head) {
  return;
  }
  Node* node = Q->head->next;
  free(Q->head);
  Q->head = node;
}
bool QueueEmpty(Queue* Q) {
  return Q->head == NULL;
}
void QueueDestroy(Queue* Q) {
  if (!Q->head) {
  return;
  }
  Node* node = Q->head->next;
  while (Q->head != Q->tail) {
  free(Q->head);
  Q->head = node;
  node = node->next;
  }
  free(Q->head);
  free(Q);
}


1-2,逻辑分析

       队列结构设置完后,我们要考虑的是如何将每一层的数据从左到右放入队列中。如果直接将树结点中的数据直接导入,很显然,这跟用不用队列结构没多大关系,相当于直接层序遍历二叉树。因此,我们要考虑将树中结点导入,然后,利用结点间相连问题进行层序导入队列中。具体步骤和说明如下:


       首先,要将根结点导入队列,然后输出队列中首结点的数据,并先将此结点的左孩子导入进队列,再将右孩子导入进队列,最后删除首结点,以此类推,不断进行循环,当队列为空时相当于已层序遍历完整个二叉树。至于原因是因为我们输出首结点的元素后删除了首结点,所以当进行下一次循环将首结点的左右孩子导入时,相当于从树的下一层开始,从左到右导入数据。


代码如下:


void LevelOrder(Tree* root) {
  //空树直接退出
  if (!root) {
  return;
  }
  //建立队列结构
  Queue* Q = (Queue*)malloc(sizeof(Queue));
  QueueInit(Q);
  //先把根结点推入进去
  QueuePush(Q, root);
  //进行遍历,先将数据输出,导入队列左右孩子后要出队,即删除,当队为空时已遍历完。
  while (!QueueEmpty(Q)) {
  fprintf(stdout, "%d ", Q->head->val->val);
  if (Q->head->val->leftchild) {
    QueuePush(Q, Q->head->val->leftchild);
  }
  if (Q->head->val->rightchild) {
    QueuePush(Q, Q->head->val->rightchild);
  }
  QueuePop(Q);
  }
}

算法演示:


//设定队列结构和必要的头文件
#include "Queue.h"
typedef struct Tree {
  int val;//数据
  struct Tree* leftchild;//左孩子结点
  struct Tree* rightchild;//右孩子结点
}Tree;
//创建二叉树数据为x的结点
Tree* CreatNode(int x) {
  Tree* node = (Tree*)malloc(sizeof(Tree));
  node->val = x;
  node->leftchild = 0;
  node->rightchild = 0;
  return node;
}
//二叉树的销毁
void TreeDestroy(Tree* root) {
  if (!root) {
  return;
  }
  TreeDestroy(root->leftchild);
  TreeDestroy(root->rightchild);
  free(root);
}
//层序遍历算法(广度优先遍历)
void LevelOrder(Tree* root) {
  //空树直接退出
  if (!root) {
  return;
  }
  //建立队列结构
  Queue* Q = (Queue*)malloc(sizeof(Queue));
  QueueInit(Q);
  //先把根结点推入进去
  QueuePush(Q, root);
  //进行遍历,先将数据输出,导入队列左右孩子后要出队,即删除,当队为空时已遍历完。
  while (!QueueEmpty(Q)) {
  fprintf(stdout, "%d ", Q->head->val->val);
  if (Q->head->val->leftchild) {
    QueuePush(Q, Q->head->val->leftchild);
  }
  if (Q->head->val->rightchild) {
    QueuePush(Q, Q->head->val->rightchild);
  }
  QueuePop(Q);
  }
}
int main()
{
  //手动构建二叉树
  Tree* node1 = CreatNode(1);
  Tree* node2 = CreatNode(2);
  Tree* node3 = CreatNode(3);
  Tree* node4 = CreatNode(4);
  Tree* node5 = CreatNode(5);
  Tree* node6 = CreatNode(6);
  Tree* node7 = CreatNode(7);
  Tree* node8 = CreatNode(8);
  Tree* node9 = CreatNode(9);
  Tree* node10 = CreatNode(10);
  Tree* node11 = CreatNode(11);
  Tree* node12 = CreatNode(12);
  Tree* node13 = CreatNode(13);
  Tree* node14 = CreatNode(14);
  Tree* node15 = CreatNode(15);
  //结点的连接
  node1->leftchild = node2;
  node1->rightchild = node4;
  node2->leftchild = node3;
  node4->leftchild = node5;
  node4->rightchild = node6;
  node2->rightchild = node7;
  node3->leftchild = node8;
  node3->rightchild = node9;
  node7->leftchild = node10;
  node7->rightchild = node11;
  node5->leftchild = node12;
  node5->rightchild = node13;
  node6->leftchild = node14;
  node6->rightchild = node15;
  LevelOrder(node1);
  TreeDestroy(node1);
  return 0;
}


接下来我们用经典题型来进行解说二叉树的运用。


【数据结构与算法】二叉树的综合运用--2https://developer.aliyun.com/article/1424486?spm=a2c6h.13148508.setting.26.214f4f0e2QJGOK

相关文章
数据结构——二叉树的链式结构
数据结构——二叉树的链式结构
36 0
|
25天前
|
算法
【算法与数据结构】二叉树(前中后)序遍历2
【算法与数据结构】二叉树(前中后)序遍历
|
10天前
二叉树和数据结构
二叉树和数据结构
17 0
|
11天前
|
算法 DataX
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
|
21天前
|
算法 索引
【算法与数据结构】深入二叉树实现超详解(全源码优化)
【算法与数据结构】深入二叉树实现超详解(全源码优化)
|
21天前
|
存储 算法
【算法与数据结构】深入解析二叉树(二)之堆结构实现
【算法与数据结构】深入解析二叉树(二)之堆结构实现
|
1月前
|
存储 算法 安全
数据结构与算法:链式二叉树
上一篇文章我们结束了二叉树的顺序存储,本届内容我们来到二叉树的链式存储!
数据结构与算法:链式二叉树
|
1月前
|
存储 算法 程序员
【数据结构】【版本2.0】【树形深渊】——二叉树入侵
【数据结构】【版本2.0】【树形深渊】——二叉树入侵
|
1月前
|
算法 C++ 开发者
【C/C++ 数据结构 】二叉树基本性质:具有n个结点的完全二叉树的深度为[log2n]+1或者[log2(n+1)]...
【C/C++ 数据结构 】二叉树基本性质:具有n个结点的完全二叉树的深度为[log2n]+1或者[log2(n+1)]...
12 0
|
1月前
|
存储 算法 C语言
【C/C++ 数据结构 树】探索C/C++中的二叉树:从理论到实践
【C/C++ 数据结构 树】探索C/C++中的二叉树:从理论到实践
60 0