【考研-数据结构】树和二叉树

这篇博客详细介绍了二叉树的相关操作,包括初始化、插入节点、先序、中序、后序遍历的递归与非递归实现,以及层次遍历。此外,还讲解了线索二叉树的概念,如何通过线索化实现快速查找前驱和后继节点。最后,讨论了二叉排序树的搜索、插入操作,并提到了平衡二叉树和哈夫曼树等高级主题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【考研-数据结构】树和二叉树

1.二叉树

#include <iostream>
#define MaxSize 20
using namespace std;
typedef struct BiTNode{
    int data;
    struct BiTNode *lchild,*rchild;
    //struct BiTNode* parent;
}BiTNode,*BiTree;


//链式队列
typedef struct LinkNode {
    BiTNode* data;
    LinkNode* next;
}LinkNode;
typedef struct {
    LinkNode* rear, * front;
}LinkQueue;
//链式队列


//初始化并建立根节点
void Init_root(BiTree& root,int e){
    //定义空树
    BiTree root = NULL;
    root = new BiTNode();
    root->data = e;
    root->lchild = nullptr;
    root->rchild = nullptr;
}
//插入第一个新节点
void Insert_Node(BiTree& root,int e){
    BiTNode* p= new BiTNode();
    p->data = e;
    p->lchild = nullptr;
    p->rchild = p;
}

//访问结点
void visit(BiTree T){
    if(T!=nullptr){
        cout<<T->data<<endl;
    }
}

//先序遍历(递归算法)
void PreOrder(BiTree T){
    if(T!=nullptr){
        visit(T);
        PreOrder(T->lchild);
        PreOrder(T->rchild);
    }
}

//先序遍历(非递归算法)(后加的,函数名可能对不上)
void PreOrder02(BiTree T){
	InitStack(S);
	BiTree p = T;
	while(p||IsEmpty(S)){
		if(p){
			visit(p);
			Push(S,p);
			p = p->lchild;
		}else{
			Pop(S,p);
			p = p->rchild;
		}
	}
}

//中序遍历
void InOrder(BiTree T){
    if(T!=nullptr){
        PreOrder(T->lchild);
        visit(T);
        PreOrder(T->rchild);
    }
}
 
//中序遍历(非递归算法)(后加的,函数名可能对不上)
void InOrder02(BiTree T){
	InitStack(S);
	BiTree p = T;
	while(p||IsEmpty(S)){
		if(p){
			Push(S,p);
			p = p->lchild;
		}else{
			Pop(S,p);
			visit(p);
			p = p->rchild;
		}
	}
}

//后序遍历
void PostOrder(BiTree T){
    if(T!=nullptr){
        PreOrder(T->lchild);
        PreOrder(T->rchild);
        visit(T);
    }
}

//求树的深度
int treeDepth(BiTree T){
    if(T == nullptr){
        return 0;
    }else{
        int l = treeDepth(T->lchild);
        int r = treeDepth(T->rchild);
        return l>r?l+1:r+1;
    }
}


//********队列操作
//初始化
void InitQueue(LinkQueue& Q) {
    Q.rear = Q.front = new LinkNode();
    Q.front->next = nullptr;
}

//判断队列是否为空
bool isEmpty(LinkQueue Q) {
    if (Q.front == Q.rear) {
        return true;
    }
    else {
        return false;
    }
}

//入队
void EnQueue(LinkQueue& Q, BiTNode *e) {
    LinkNode* temp = new LinkNode();
    temp->data = e;
    temp->next = nullptr;
    Q.rear->next = temp;
    Q.rear = temp;
}

//出队
bool DeQueue(LinkQueue& Q, BiTNode*& x) {
    if (Q.front == Q.rear) return false;
    LinkNode* temp = Q.front->next;
    x = temp->data;
    Q.front->next = Q.front->next->next;
    if (Q.front->next == nullptr) {
        Q.rear = Q.front;
    }
    delete temp;
    return true;
}
//********队列操作




//层次遍历:初始化一个辅助队列,如果队列非空则队头出一个结点
//然后将弹出的结点的左右结点按顺序入队
void LevelOrder(BiTree T){
    LinkQueue Q;
    InitQueue(Q);                 //初始化辅助队列
    BiTree p;
    EnQueue(Q,T);           //根节点入队
    while(!isEmpty(Q)){           //队列不空的时候循环
        DeQueue(Q,p);       //队头结点出队
        visit(p);                 //访问处对接点
        if(p->lchild!=nullptr){
            EnQueue(Q,p->lchild); //左节点入队
        }
        if(p->rchild!=nullptr){
            EnQueue(Q,p->rchild); //右节点入队
        }
    }
}

//根据遍历创建二叉树(中序加其余任意一种)

int main() {



    return 0;
}


2.线索二叉树

#include<iostream>
using namespace std;
//线索二叉树
//作用:方便从一个指定结点出发,找到其前驱和后继节点,方便遍历
typedef struct ThreadNode{
    int data;
    struct ThreadNode *lchild,*rchild;
    int ltag,rtag;
    //左右线索标志位 
    //(tag=0的时候指向左右孩子,tag=1的时候指向线索,表示指向前驱和后继
}ThreadNode,*ThreadTree;

//普通二叉树
typedef struct BiTNode{
    int data;
    struct BiTNode *lchild,*rchild;
    //struct BiTNode* parent;
}BiTNode,*BiTree;


//中序线索化01(笨方法)
void InOrder(BiTree T){
    if(T!=nullptr){
        InOrder(T->lchild);
        visit(T);
        InOrder(T->rchild);
    }
}
BiTNode* p;
BiTNode* pre = nullptr;
BiTNode* final = nullptr;
void visit(BiTNode *q){
    if(q == p){
        final = pre;
    }else{
        pre = q;
    }
}
//中序线索化02(最后一个结点要特殊处理)
ThreadNode* pre02 = nullptr;
void CreateInThread(ThreadTree T){
    pre02 = nullptr;
    if(T!=nullptr){
        InThread(T);
        //处理最后一个结点
        if(pre02->rchild == nullptr){
            pre02->rtag = 1;
        }
    }
}
void InThread(ThreadTree T){
    if(T!=nullptr){
        InThread(T->lchild);
        visit02(T);
        InThread(T->rchild);
    }
}
void visit02(ThreadNode *q){
    if(q->lchild == nullptr){
        q->lchild = pre02;
        q->ltag = 1;
    }
    if(pre!=nullptr&&pre->rchild == nullptr){
        pre02->rchild = q;
        pre02->rtag = 1;
    }
    pre02 = q;
}


//前序线索化
ThreadNode* pre03 = nullptr;
void CreatePreThread(ThreadTree T){
    pre03 = nullptr;
    if(T!=nullptr){
        InThread(T);
        //处理最后一个结点
        if(pre03->rchild == nullptr){
            pre03->rtag = 1;
        }
    }
}
void PreThread(ThreadTree T){
    if(T != nullptr){
        visit03(T);
        if(T->ltag == 0){
            PreThread(T->lchild);
        }
        PreThread(T->rchild);
    }
}
void visit03(ThreadNode* q){
    if(q->lchild == nullptr){
        q->lchild = pre03;
        q->ltag = 1;
    }
    if(pre03!=nullptr&&pre03->rchild == nullptr){
        pre03->rchild = q;
        pre03->rtag = 1;
    }
    pre03 = q;
}


//后序线索化
ThreadNode* pre04 = nullptr;
void CreatePostThread(ThreadTree T){
    pre04 = nullptr;
    if(T!=nullptr){
        InThread(T);
        //处理最后一个结点
        if(pre04->rchild == nullptr){
            pre04->rtag = 1;
        }
    }
}
void PostThread(ThreadTree T){
    if(T != nullptr){
        PostThread(T->lchild);
        PostThread(T->rchild);
        visit03(T);
    }
}
void visit03(ThreadNode* q){
    if(q->lchild == nullptr){
        q->lchild = pre04;
        q->ltag = 1;
    }
    if(pre04!=nullptr&&pre04->rchild == nullptr){
        pre04->rchild = q;
        pre04->rtag = 1;
    }
    pre04 = q;
}


//中序线索二叉树找中序后继

//找到以p为跟的子树中,第一个被中序遍历的结点
ThreadNode*Firstnode(ThreadNode*p){
    //循环找到最左下结点(不一定是叶子结点)
    while(p->ltag == 0) p = p->lchild;
    return p;
}
//在中序线索二叉树中找到结点p的后继节点
ThreadNode*Nextnode(ThreadNode*p){
    //右子树中最左下结点
    if(p->rtag == 0) return Firstnode(p->rchild);
    //p->rtag == 1,p->rchild就是后继
    else return p->rchild;  
}
//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法)
void InOrder(ThreadNode* T){
    for(ThreadNode* p = Firstnode(T);p!=nullptr;p = Nextnode(p)){
        visit_zb(p);
    }
}
void visit_zb(ThreadNode* p){
    if(p!=nullptr){
        cout<<p->data<<endl;
    }
}


//中序线索二叉树找中序前驱

//找到以p为跟的子树中,最后一个被中序遍历的结点
ThreadNode*Lastnode(ThreadNode*p){
    //循环找到最右下结点(不一定是叶子结点)
    while(p->rtag == 0) p = p->rchild;
    return p;
}
//在中序线索二叉树中找到结点p的前驱结点
ThreadNode *Prenode(ThreadNode*p){
    //左子树中最右下结点
    if(p->ltag == 0) return Lastnode(p->lchild);
    //p->ltag == 1,p->lchild就是前驱结点
    else return p->lchild;
}
//对中序线索二叉树进行逆向中序遍历
void ReInorder(ThreadNode*T){
    for(ThreadNode *p = Lastnode(T);p!=nullptr;p = Prenode(p)){
        visit_zb(p);
    }
}

//先序线索二叉树中找先序后继
//1.p->rtag == 1,next = p->rchild
//2.p->rtag == 0,若p有左孩子,则先序后继为左孩子,
//若p没有左孩子,则先序后继为右孩子

//先序线索二叉树找先序前驱
//1.p->ltag == 1,pre = p->lchild
//2.p->ltag == 0
//(找不到,除非用土方法,再次遍历二叉树,见上,也可用三叉链表,加一个父亲结点)


//后序线索二叉树找后续先驱
//1.p->ltag == 1.pre = p->lchild
//2.p->ltag == 0.若p有右孩子,则前驱为右孩子
//若p没有右孩子,则前驱为左孩子

//后续线索二叉树找找后续后继
//1.p->rtag == 1.next = p->rchild
//2.p->rtag == 0,
//(找不到,除非用土方法,再次遍历二叉树,见上,也可用三叉链表,加一个父亲结点)


int main() {

    return 0;
}

3.二叉排序树和森林

//树和森林
#include<iostream>
using namespace std;

//树的先根遍历和对应二叉树的先序遍历相同(深度优先遍历)
//树的后根遍历和对应二叉树的中序遍历相同(深度优先遍历)
//树的层次遍历与二叉树相同(广度优先遍历)

//森林的先序遍历和对应二叉树的先根遍历相同
//森林的中序遍历等同于依次对每个树进行后根遍历(对应二叉树的中序遍历)


//二叉排序树
//左节点<根结点值<右结点值
typedef struct BSNode{
    int key;
    struct BSNode *lchild,*rchild;
}BSTNode,*BSTree; 
//1.搜索
//非递归
BSTNode*BST_Search(BSTree T,int key){
    while(T!=nullptr&&T->key!=key){
        if(key>T->key) T = T->rchild;
        else T = T->lchild;
    }
    return T;
}
//递归实现
BSTNode*BST_Search02(BSTree T,int key){
    if(T == nullptr) return nullptr;
    if(key == T->key) return T;
    else if(key<T->key) return BST_Search02(T->lchild,key);
    else return BST_Search02(T->rchild,key);
}

//2.插入
//递归实现
int BST_Insert(BSTree &T,int k){
    if(T == nullptr){
        T = new BSTNode();
        T->key = k;
        T->lchild = T->rchild = nullptr;
        return 1;  //返回1,插入成功
    }
    else if(k == T->key) 
        return 0;
    else if(k < T->key){
        return BST_Insert(T->lchild,k);
    }
    else if(k > T->key){
        return BST_Insert(T->rchild,k);
    }
    return 0;
}
//非递归实现(需要改动)
int BST_Insert02(BSTree &T,int k){
    while(T!=nullptr){
        if(k<T->key){
            T = T->lchild;
        }else if(k>T->key){
            T = T->rchild;
        }else if(k == T->key){
            return 0;
        }
    }
    T = new BSTNode();
    T->key = k;
    T->lchild = T->rchild = nullptr;
    return 1;
}

//二叉排序树的构造
void Create_BST(BSTree &T,int str[],int n){
    T = nullptr;
    int i = 0;
    while(i<n){
        BST_Insert(T,str[i]);
        i++;
    }
}

//二叉排序树的删除(删除之后,使用直接前驱或者直接后继来代替)
//1.被删节点是叶子结点,直接删除
//2.被删节点只有左子树或者只有右子树,用其子树定顶替位置
//3.被删节点有左子树和右子树:
//  (1)可用其后继节点顶替,再删除后继节点
//  (2)可用其前驱节点顶替,再删除前驱节点
//  (3)前驱:左子树最右下角的结点
//  (4)后继:右子树中最左下角的结点


//平衡二叉树(查找效率O(log2(n)))
//左节点进行右旋转
//右节点进行左旋转

//哈夫曼树(最优二叉树)






int main() {
    BSTree T;
    //T = new BSTNode();
    //T->lchild = nullptr;
    //T->rchild = nullptr;
    //T->key = 1;
    int str[] = {2,3};
    Create_BST(T,str,2);
    cout<<T->key<<endl;
    //cout<<T->rchild->key<<endl;
    //cout<<T->rchild->rchild->key<<endl;
    /*
    cout<<BST_Insert(T,2)<<endl;
    cout<<BST_Insert(T,1)<<endl;
    cout<<BST_Insert(T,3)<<endl;
    cout<<"---"<<endl;
    cout<<T->key<<endl;
    cout<<T->lchild->key<<endl;
    cout<<T->rchild->key<<endl;
    */

    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值