IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【数据结构】二叉树 -> 正文阅读

[数据结构与算法]【数据结构】二叉树

目录

1.介绍

? ? ? ? 1.1.二叉树

????????1.2.满二叉树

2.二叉树的存储结构

????????2.1.二叉树的顺序存储

? ? ? ? 2.2.二叉树的链式存储

3.二叉树的建立

4.二叉树的遍历

? ? ? ? 4.1.二叉树的递归遍历

? ? ? ? 4.2.二叉树的非递归遍历

? ? ? ? 4.3.二叉树的层次遍历


1.介绍

? ? ? ? 1.1.二叉树

????????什么是二叉树,想要知道二叉树,我们需先知道树的概念 。树(tree)?是n(n>=0)个结点的有限集。n=0时称为空树。在任何一棵非空树中:1. 有且只有一个特定的称为?根(root)?的结点;2. 当n>1时,其余结点可分为m(m>0)个?互不相交?的有限集,其中每一个集合又是一棵树,并且成为?根的子树(subtree),树是一种一对多的结构。

?二叉树,就是度最多只有2的树,通俗的讲,就是每个结点最多只能有两个分支。

????????1.2.满二叉树

? ? ? ? 满二叉树就是满足以下性质的二叉树:

????????1.满二叉树中第 i 层的结点数为 2n-1?个。

????????2.深度为 k 的满二叉树必有 2k-1 个结点 ,叶子数为 2k-1。

????????3.满二叉树中不存在度为 1 的结点,每一个分支点中都两棵深度相同的子树,且叶子结点都在最底层。

2.二叉树的存储结构

????????二叉树的存储结构分为两种,顺序存储和链式存储。

????????2.1.二叉树的顺序存储

? ? ? ? 二叉树的存储结构利用数组的形式存储,并按照满二叉树的顺序排序,没有的地方存0即可。

输入方式按照层次自左向右依次输入即可,即是按照满二叉树的顺序。

#include<stdio.h>
#define Max 100
typedef int Sqbitree[Max];

?

? ? ? ? 2.2.二叉树的链式存储

? ? ? ? 二叉树的链式存储结构通过链表的形式实现,首先,作为二叉树,需要两个分支分别代表下一个结点,我们将两个结点分别命名为左、右孩子,以及本身的数据域

typedef struct _bisq
{
    int date;                        //数据域
    struct _bisq *lchild;            //左孩子
    struct _bisq *rchild;            //右孩子
}BiNode;

3.二叉树的建立

? ? ? ? 二叉树的建立分为三种:前序建立,中序建立,以及后序建立。前序建立就是先输入根结点,再输入左子树,最后输入右子树,即根左右;中序建立就是左根右,后序建立就是左右根

这里抽出前序建立进行评说:

二叉树的前需建立通过递归的形式实现,对每一个分支进行建立,直到输入为空(自定义一个字符)

void BiTreeCreate(BiTree *p)   //二叉树的前序建立
{
    char ch;                //数据域初始化
    scanf("%c",&ch);
    if ( ch == '#' )        //判断是否终止
        p = NULL;
    else
    {
        p = (BiTree*)malloc(sizeof(BiTree));        //给该结点赋予空间
        if ( !p )            
            exit(0);
        p->data = ch;                   //前序中序后序的区别就在于此行代码位置
        BiTreeCreate(p->lchild);        //若上行代码位于这就是中序,后序就在下一行
        BiTreeCreate(p->rchild);
     /*不要小看代码的位置,由于递归的原因,一个位置的变化引起的因果是很大的*/
    }
}

4.二叉树的遍历

? ? ? ? 4.1.二叉树的递归遍历

? ? ? ? 二叉树的递归遍历分为前序遍历,中序遍历和后序遍历,代码比较简单,看一下基本都能理解:

void PreorderTraverse(BiTree *p)        //遍历函数
{
    if ( p == NULL )                //判断树是否为空
        return ;
    else
    {
        printf("%c",p->data);        //遍历
        PreorderTraverse(p->lchild);        //左孩子遍历
        /*先序中序后序的区别就是printf函数在哪一行的区别,在第一行就是先序,
        在第二行就是中序,在第三行就是后序*/
        PreorderTraverse(p->rchild);        //右孩子遍历
    }
}

? ? ? ? 4.2.二叉树的非递归遍历

? ? ? ? 非递归遍历如何实现?主要是运用栈先进后出的思想进行遍历,既然要用到栈,我们就需要一些有关栈的函数

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Max 9999


typedef struct _Sq
{
    char data;
    int Cishu;        //后序遍历需要
    struct _Sq *lchild,*rchild;
}BiTree;

typedef struct _stack
{
    BiTree *elements[Max];
    int top;
}SetStack;

SetStack S;

void setnull()   //初始化栈
{
    S.top = 0;
}

void push(BiTree *p)            //栈入函数
{
    S.elements[S.top++]=p;
}

BiTree *pop()                    //栈出函数
{
    return S.elements[--S.top];
}

前序非递归遍历:根左右,扫描二叉树,将根存入栈,再存入左子树,在对左子树进行上一步操作,直到左子树遍历完成,存入右子树,重复操作进行遍历(由于前序和中序思想类似,不再逐个解释)

void preorder(BiTree *p)  //前序非递归遍历 (根左右)
{
    BiTree *t = p;
    while ( t != NULL || S.top !=0 )            //若结点不为空或栈不为空时
    {
        while ( t != NULL )                    //若结点不为空,重复操作,对每一个子树
        {
            printf("%4c",t->data);                //遍历根结点
            push(t);                              //根结点入栈
            t = t->lchild;                        //访问左子树
        }
        if ( S.top != 0 )                        //若栈不为空
        {
            t = pop();                            //出栈上一个存入的结点
            t = t->rchild;                        //对上一个结点的右子树进行遍历
        }
    }
}
void inorder(BiTree *p)  //中序非递归遍历(左根右)
{
    BiTree *t = p;
    while ( t != NULL || S.top != 0 )
    {
        while ( p != NULL )
        {
            push(t);
            p = p->lchild;
        }
        if ( S.top != 0 )
        {
            t = pop();
            printf("%4c",p->data);
            t = t->rchild;
        }
    }
}

后序非递归遍历:特殊处理,由于后序遍历会经过两次根结点,所以会多出一个cishu变量,在第一次经过时不对其进行遍历,直至第二次才遍历

void laorder(BiTree *p)   //后序非递归遍历
{
    BiTree *t = p;
    {
        while ( t != NULL || S.top != 0 )
        {
            t->Cishu = 1;
            push(t);
            t = t->lchild;
        }
        if ( S.top != 0 )
        {
            t = pop();
            if ( t->Cishu == 1 )  //第一次被访问
            {
                t->Cishu++;
                push(t);
                t = t->rchild;
            }
            else
            {
                if ( t->Cishu == 2 )  //第二次被访问,制空,防止陷入死循环
                {
                    printf("%4c",t->data);
                    t = NULL;
                }
            }
        }
    }

? ? ? ? 4.3.二叉树的层次遍历

? ? ? ? 二叉树的层次遍历主要通过队列先进先出的思想实现:所以我们需要一些有关队列的函数

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Max 9999
typedef struct _Sq{
    char date;
    struct _Sq *lchild,*rchild;
}BiTree;



//实现思路:利用队列先进先出的思想

typedef struct _queue{
    BiTree *elements[Max];
    int front;
    int real;
}SetQueue;

SetQueue *p;


void InitQueue(){            //队列初始化
    p->front = p->real = 0;
}

void Push (BiTree* s) {        //入队
    p->elements[++p->real] = s;
}

BiTree* Pop() {            //出队
    return p->elements[++p->front];
}

int empty() {            //判断是否队列为空
    return p->real == p->front;
}
void levelorder() {
    BiTree* t;
    if (t != NULL) {        //如果树不为空
        Push(t);            //将当前结点入队
    }
    while (!empty()) {        //判断队列是否空
        t = Pop();            //出队
        printf("%4c",t->date);        //遍历
        if (t->lchild != NULL) {        
            Push(t->lchild);        //如果左子树不为空,入队
        }
        if (t->rchild != NULL) {
            Push(t->rchild);        //如果右子树不为空,入队
        }
    }
}

//由于队列先进先出的思想,所有的子树就会排在根结点的后面,按照层次遍历就实现了
//不能理解的可以用笔举个实例,按照代码进行操作

?以上就为二叉树的一些遍历方法和建立方法~

如果有什么错误请指出~笔者会及时更改

多多担待~~

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-15 18:33:00  更:2021-12-15 18:33:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:53:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码