[Postgraduate Entrance Examination Review] Special storage of binary trees | Trinomial linked lists store binary trees, one-dimensional arrays store binary trees, and clue binary trees

Triplet linked list stores binary tree

The three-pronged linked list structure is represented as follows:

How to construct a three-pronged linked list:

typedef struct node{
    
    
    char data;
    struct node*parent,*lchild,*rchild;
}BTNode,*BiTree;
BTNode * creattree(BiTree &t){
    
     // 易错点:树的引用
    char ch;
    cin>>ch;
    if(ch=='#'){
    
    
        t=NULL;
    }else{
    
    
        t=(BTNode*)malloc(sizeof(BTNode));// 易错点:忘记重新创建新结点
        t->data=ch;
        t->parent=NULL;
        t->lchild=NULL;
        t->rchild=NULL;
        if(t->lchild) t->lchild->parent=t;
        if(t->rchild) t->rchild->parent=t;
        creattree(t->lchild);
        creattree(t->rchild);
    }
    return t;
}

In addition, a filling function is designed. The function of the function is to fill the parent nodes of all nodes correctly.

void FillParent(BiTree &root){
    
    
    if(root==NULL) return;
    if(root->lchild) {
    
    
        root->lchild->parent=root;
        FillParent(root->lchild);
    }
    if(root->rchild){
    
    
        root->rchild->parent=root;
        FillParent(root->rchild);
    }
}

Preorder traversal of trident linked list (without stack) Method 1

void PreOrder(BiTree t){
    
       //访问顺序:根左右
    BTNode *p;
    while(t){
    
    
        visit(t);//访问根
        if(t->lchild) t=t->lchild;//找到左下结点,下一次就循环访问左
        else if(t->rchild) t=t->rchild;//下一次循环访问右
        else{
    
    //如果当前结点既没有左孩子也没有有孩子
            while(1){
    
    //一直往上回溯到有非空的父亲结点、同时找到二叉树的那个“叉”
                p=t;//p指向根t
                t=t->parent;//t指向父亲结点
                if(!t) break;//如果t为空,则说明该节点是空结点,排除这种情况
                if(t->lchild==p&&t->rchild) break;//如果t的左孩子是p且t的右孩子不为空,跳出while之后到右结点
            }
            if(t)t=t->rchild;//往右边访问
        }
    }
}

Preorder traversal of trident linked list (without stack) Method 2

// 【题目】二叉树采用三叉链表的存储结构,试编写
// 不借助栈的非递归中序遍历算法。
// 三叉链表类型定义:
typedef struct TriTNode
{
    
    
    char data;
    struct TriTNode *parent, *lchild, *rchild;
} TriTNode, *TriTree;

void InOrder(TriTree PT, void (*visit)(char))
/* 不使用栈,非递归中序遍历二叉树PT,  */
/* 对每个结点的元素域data调用函数visit */
{
    
    
    TriTree p = PT, pr;
    while (p)
    {
    
    
        if (p->lchild)
            p = p->lchild; // 寻找最左下结点
        else
        {
    
    
            visit(p->data); // 找到最左下结点并访问
            if (p->rchild)
            {
    
    
                p = p->rchild; // 若有右子树,转到该子树,继续寻找最左下结点
            }
            else
            {
    
    
                pr = p; // 否则返回其父亲
                p = p->parent;
                while (p && (p->lchild != pr || !p->rchild))
                {
    
                            // 若其不是从左子树回溯来的,或左结点的父亲并没有右孩子
                    if (p->lchild == pr) // 若最左结点的父亲并没有右孩子
                        visit(p->data);  // 直接访问父亲(不用转到右孩子)
                    pr = p;              // 父亲已被访问,故返回上一级
                    p = p->parent;       // 该while循环沿双亲链一直查找,若无右孩子则访问,直至找到第一个有右孩子的结点为止(但不访问该结点,留给下步if语句访问)
                }
                if (p)
                {
    
     // 访问父亲,并转到右孩子(经上步while处理,可以确定此时p有右孩子)
                    visit(p->data);
                    p = p->rchild;
                }
            }
        }
    }
}

One-dimensional array stores binary tree

// 动态输入
void CreateTreeArray(int a[], int n)
{
    
    
    char ch;
    for (int i = 0; i < n; i++)
    {
    
    
        cin >> ch;
        a[i] = ch;
    }
}

Preorder traversal of binary tree stored in one-dimensional array

// 前序遍历
#define Maxsize 50
typedef struct BTNodeArray
{
    
    
    int data[Maxsize];
    int length;
} BTNodeArray;
void PreOrderArray(BTNodeArray t, int i)
{
    
    
    if (i >= t.length)
        return;
    printf("%d", t.data[i]);
    PreOrderArray(t, i * 2);     // 遍历左子树
    PreOrderArray(t, i * 2 + 1); // 遍历右子树
}

Creation of clue binary tree

The basic structure of the clue binary:

Use inorder traversal order for clueing. There is an incomprehensible point in the code. Why not use p to find the successor directly, but use the predecessor node to find the successor. In fact, it is not that p is not used to find the successor, but that the successor cannot be found from p, so we can only find the successor of the predecessor indirectly. This way of finding the successor, once you understand this, the code will not be difficult to understand.

//中序遍历线索化
void InOrder(ThreadTree &p,ThreadTree &pre){
    
    
    if(p!=NULL){
    
    
        InOrder(p->lchild,pre);
        if(p->lchild==NULL){
    
        //只能通过当前结点找前驱
            p->lchild=pre;
            p->ltag=1;
        }
		if(pre!=NULL&&pre->rchild==NULL){
    
      //只能通过前驱结点找后继
            pre->rchild=p;
            pre->rtag=1;
        }
        pre=p;
        InOrder(p->rchild,pre);
    }
    return;
}
void InOrderThread(ThreadTree t){
    
    
    ThreadNode *pre=NULL;
    if(t!=NULL){
    
    
        InOrder(t,pre);
        pre->rchild=NULL;
        pre->rtag=1;
    }
}

Traversal of binary trees with inorder clues

//中序线索二叉树的遍历
//--最左下的结点
ThreadTree FirstNode(ThreadTree p){
    
    
    while(p->ltag==0) p=p->lchild;
    return p;
}
//--结点的后继
ThreadTree NextNode(ThreadTree p){
    
    
    if(p->rtag==0) p=p->rchild;
    else FirstNode(p->rchild);
}
//--开始遍历
void InOrderThreadCount(ThreadTree t){
    
    
    for(ThreadNode *p=FirstNode(t);p!=NULL;p=NextNode(p)) cout<<p->data<<endl;
}

Practice questions

Insert image description here

//建立三叉链表,
//删除每一个元素为x的结点,以及以他为根的子树且释放相应存储空间
#include<iostream>
using namespace std;

void BuildTree(BiTree &t){
    
    
    char ch;
    cin>>ch;
    if(ch=='#'){
    
    
        t=NULL;
    }else{
    
    
        t=(BTNode *)malloc(sizeof(BTNode));
        t->data=ch;
        t->parent=NULL;
        t->lchild=NULL;
        t->rchild=NULL;
        if(t->lchild) t->lchild->parent=t;
        if(t->rchild) t->rchild->parent=t;
        BuildTree(t->lchild);
        BuildTree(t->rchild);
    }
}
void Destory(BiTree t){
    
    
    if(t==NULL) return;
    if(t->lchild) Destory(t->lchild);
    if(t->rchild) Destory(t->rchild);
    free(t);    //释放根节点
    t=NULL;     //空指针赋值0
}
void DeleteX(BiTree &t,char x){
    
    
    if(t==NULL) return;
    if(t->data==x) Destory(t);
    DeleteX(t->lchild,x);
    DeleteX(t->rchild,x);
}

Guess you like

Origin blog.csdn.net/m0_52427832/article/details/133418374