数据结构之树

树的基本概念

定义

树是n(n>=0)的结点的有限集。

n个结点的树有n-1的边(根结点无上层结点)

树中结点最大度数称为树的度

结点的扇出为结点的度

深度为结点所在层次(从根开始定义)

结点高度是以该结点为根的子树的高度

路径长度是路径经过的边的个数

度的计算

树的结点数是所有度数之和加一

度为m的树中第i层至多为m^{i-1}个结点

高度h的m叉树至多(m^{h}-1)/m-1结点

二叉树

非空二叉树上叶结点等于度为2的结点数加1,n0=n2+1

含n结点的二叉链表中有n+1个空链域(总共2n减去用了n-1个)

二叉树遍历与线索二叉树

二叉树遍历

先序遍历

根左右

中序遍历

左根右

后序遍历

左右根

层序遍历

构造链表队列,先将根节点加入队列,接下来不断判队列是否为空作为出口条件,每出队一个结点就加入它的左右孩子(如果存在的话),然后出队根节点开始层次遍历。

由遍历构造树

给出两个或多个遍历完善树的结构

前序加中序

后序加中序

层次加中序

综上可以看出,中序是可以构造树的必要序列。

构造过程即是通过前/层次/后确定根的位置在中序中划分根以及他的左右结构并不断如此划分下去。

线索二叉树

概念

利用空下的n+1指针域来得到有前驱后继的线性序列。实现概述:左子树为空则指向前驱,右子树为空则指向后继。

粗略实现

中序前驱结点法:指定要找的结点后,以指针p指向它,然后根据中序遍历顺序,以q指向中序遍历第一个结点并伴随一个结果指针final,然后依次访问,若q,p不等时则把结果指针留在q现在的位置让q访问下一个,那么此时final即是q的前序,以此类推直到q,p相等,此时的final就是想要目标结点的前序即所求。
先序:注意不要“转圈”成环遍历

具体函数如下图,复制代码汇在合集里

线索二叉树定义下的实现请参考王道书

代码汇总

// Tree-WangDao.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <stack>
using namespace std;
//顺序存储
#define MaxSize 100
struct TreeNode {//完全二叉树
    int value;
    bool isEmpty;
};
typedef struct BiTNode {//完全二叉树
    int data;
    struct BiTNode* lchild, * rchild;
    struct BiTNode* parent;//加上即为三叉链表
}BiTNode,*BiTree;
BiTNode* p;//目标节点
BiTNode* pre = NULL;//当前结点的前驱
BiTNode* final = NULL;//最终结果
void visit(BiTNode* q)
{
    if (q == p)
        final = pre;
    else
        pre = q;


}
BiTree PreOrder(BiTree T)
{
    if (!T)
    {
        cout << T->data;
        cout << PreOrder(T->lchild);
        cout << PreOrder(T->rchild);

     }

}
BiTree InOrder(BiTree T)//右根,递归

{
    if (!T)
    {
        
        cout << InOrder(T->lchild);
       // cout << T->data;
        visit(T);
        cout << InOrder(T->rchild);

    }

}
static void NonRecPreOrder(BiTree t) {//右根,非递归
   stack<BiTree> S; BiTree p = t;
    while (true) {
        while (p != NULL) {//自上而下沿左分支访问
            cout << p->data;
            S.push(p);
            p = p->lchild;
        }
        if (S.empty()) return;
         S.pop(); //自下而上访问各右子树
        p = p->rchild;
    }
}
BiTree InOrder(BiTree T)//中根
{
    if (!T)
    {

        cout << InOrder(T->lchild);
        cout << T->data;
        cout << InOrder(T->rchild);

    }

}
static void NonRecInOrder(BiTree t) {//中根,非递归
    stack<BiTree> S; BiTree p = t;
    while (true) {
        while (p != NULL) {//自上而下沿左分支访问
            
            S.push(p);
            p = p->lchild;
        }
        if (S.empty()) return;
       S.pop(); //自下而上访问各右子树 
        cout << p->data;
        p = p->rchild;
    }
}
BiTree PostOrder(BiTree T)//后根
{
    if (!T)
    {

        cout << PostOrder(T->lchild);
        cout << PostOrder(T->rchild); 
        cout << T->data;

    }

}
static void NonRecPostOrder(BiTree t) {//后根,非递归
    stack<BiTree> S; BiTree p = t, pre = NULL;
    while (true) {
        while (p != NULL) {//自上而下沿左分支访问

            S.push(p);
            p = p->lchild;
        }
        if (S.empty()) return;
        p = S.top();
        if (p->rchild == NULL || p->rchild == pre) {
             S.pop();  cout << p->data; pre = p; p = NULL;
        }
        else
            p = p->rchild;
    }
        cout << p->data;
    }

int main()
{
    TreeNode t[MaxSize];//顺序存储
    for (int i = 0;i < MaxSize;i++)//初始化
        t[i].isEmpty = true;
    BiTree root = NULL;//链式存储
    //插入根节点,初始化
    root = (BiTree)malloc(sizeof(BiTree));
    root->data = 1;
    root->lchild = NULL;
    root->rchild = NULL;
}

注言

按自己节奏来,少管别人多做自己,智者向内寻求力量。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值