• 2021.10.19数据结构实验课作业——树的操作和应用


    1、二叉树的基本操作(必做题)
    (1) 使用二叉链表构建二叉树;
    (2) 实现二叉树的前序、中序和后序遍历,包括递归算法和非递归算法;
    (3) 统计二叉树的深度;
    (4) 在二叉树中查找值为X的节点,若存在输出Yes,不存在输出No。

    点击查看代码BiTree.h
    #pragma once
    
    #include <iostream>
    using namespace std;
    
    template <typename T>
    struct BiNode {
    	T data;
    	BiNode<T> *lchild, *rchild;
    	BiNode<T>(T x, BiNode<T> *l, BiNode<T> *r) {
    		data = x;
    		lchild = l, rchild = r;
    	}
    };
    template <typename T>
    class BiTree {
    public:
    	BiTree() { root = Creat(); }
    	~BiTree() { Release(root); }
    	void PreOrder() {
    		PreOrder(root);
    		cout << endl;
    	}
    	void InOrder() {
    		InOrder(root);
    		cout << endl;
    	}
    	void PostOrder() {
    		PostOrder(root);
    		cout << endl;
    	}
    	int GetDeep() { return GetDeep(root); }
    	BiNode<T>* GetRoot() { return root; }
    private:
    	BiNode<T> *Creat() {
    		BiNode <T> *bt;
    		char ch;
    		cin >> ch;
    		if (ch == '#')
    			bt = NULL;
    		else {
    			BiNode<T>* l = Creat();
    			BiNode<T>* r = Creat();
    			bt = new BiNode<T>(ch, l, r);
    		}
    		return bt;
    	}
    	void Release(BiNode<T> *bt) {
    		if (bt == NULL) return;
    		Release(bt->lchild);
    		Release(bt->rchild);
    		delete bt;
    	}
    	void PreOrder(BiNode<T> *bt) {
    		if (bt == NULL) return;
    		cout << bt->data << ' ';
    		PreOrder(bt->lchild);
    		PreOrder(bt->rchild);
    	}
    	void InOrder(BiNode<T> *bt) {
    		if (bt == NULL) return;
    		InOrder(bt->lchild);
    		cout << bt->data << ' ';
    		InOrder(bt->rchild);
    	}
    	void PostOrder(BiNode<T> *bt) {
    		if (bt == NULL) return;
    		PostOrder(bt->lchild);
    		PostOrder(bt->rchild);
    		cout << bt->data << ' ';
    	}
    	int GetDeep(BiNode<T> *bt) {
    		if (bt == NULL)
    			return 0;
    		int l = GetDeep(bt->lchild),
    			r = GetDeep(bt->rchild);
    		return max(l, r) + 1;
    	}
    	BiNode<T> *root;
    };
    

    Stack.h

    点击查看代码Stack.h
    //栈基本实现
    #pragma once
    
    const int Maxn = 1001;
    template <typename T>
    class Stack {
    private:
    	int top;
    	T sta[Maxn];
    public:
    	Stack() {
    		top = 0;
    	}
    	Stack(int n, T a[]) {
    		top = n;
    		for (int i = 0; i < n; ++i)
    			sta[i] = a[i];
    	}
    	void Push(T x) {
    		if (top == Maxn) throw "Fulled!";
    		sta[top++] = x;
    	}
    	T Pop() {
    		if (Empty()) throw "Empty!";
    		return sta[--top];
    	}
    	T GetTop() {
    		if (Empty()) throw "Empty!";
    		return sta[top-1];
    	}
    	bool Empty() {
    		return top == 0;
    	}
    };
    

    main.cpp

    点击查看代码main.cpp
    /*
     * 都在书上有
     * 非递归算法可以用栈模拟递归(不过课本上不是这么写的)
     */
    #include <iostream>
    #include "BiTree.h"
    #include "Stack.h"
    using namespace std;
    
    template<typename T>
    struct Element
    {
        BiNode<T>* ptr;
        int flag;//flag=1表示左子树已经入栈,=2表示右子树已经入栈
        Element() {
            ptr = NULL, flag = 0;
        }
        Element(BiNode<T>* p, int x) {
            ptr = p, flag = x;
        }
    };
    
    template <typename T>
    class MyTree : public BiTree<T> {
    public:
        bool ExistX(T x) { return ExistX(BiTree<T>::GetRoot(), x); }//按值查找
        void PreOrderNeg() {
            Stack<BiNode<T>* > sta;
            BiNode<T>* bt = BiTree<T>::GetRoot();
            sta.Push(bt);
            while (!sta.Empty()) {
                bt = sta.Pop();
                cout << bt->data << ' ';
                if (bt->rchild != NULL)
                    sta.Push(bt->rchild);
                if (bt->lchild != NULL)
                    sta.Push(bt->lchild);
            }
            cout << endl;
            return;
        }
        void InOrderNeg() {
            Stack<BiNode<T>* > sta;
            BiNode<T>* bt = BiTree<T>::GetRoot();
            while (bt != NULL || !sta.Empty()) {
                while (bt != NULL) {
                    sta.Push(bt);
                    bt = bt->lchild;
                }
                if (!sta.Empty()) {
                    bt = sta.Pop();
                    cout << bt->data << ' ';
                    bt = bt->rchild;
                }
            }
            cout << endl;
            return;
        }
        void PostOrderNeg() {
            Stack<Element<T> > sta;
            BiNode<T>* bt = BiTree<T>::GetRoot();
            while (bt != NULL || !sta.Empty()) {
                while (bt != NULL) {
                    sta.Push(Element<T>(bt, 1));
                    bt = bt->lchild;
                }
                while (!sta.Empty() && sta.GetTop().flag == 2) {
                    bt = sta.Pop().ptr;
                    cout << bt->data << ' ';
                }
                if (!sta.Empty()) {
                    Element<T> x = sta.Pop();
                    x.flag = 2;
                    sta.Push(x);
                    bt = (x.ptr)->rchild;
                }
                else    bt = NULL;
            }
            cout << endl;
            return;
        }
    private:
        bool ExistX(BiNode<T>* bt, T x) {
            if (bt == NULL) return false;
            if (x == bt->data)
                return true;
            return ExistX(bt->lchild, x) || ExistX(bt->rchild, x);
        }
    };
    
    int main() {
        cout << "Please creat the tree_a;" << endl;
        MyTree<char> tree_A;
        cout << "PreOrder:" << endl;
        tree_A.PreOrderNeg();
        tree_A.PreOrder();
        cout << "InOrder:" << endl;
        tree_A.InOrderNeg();
        tree_A.InOrder();
        cout << "PostOrder:" << endl;
        tree_A.PostOrderNeg();
        tree_A.PostOrder();
        cout << "The depth is: " << tree_A.GetDeep() << endl;
        char x;
        cout << "Search: ";
        cin >> x;
        cout << (tree_A.ExistX(x) ? "Yes" : "NO");
        return 0;
    }
    /*
    A B D E # # # F # #
    C G # # #
    */
    

    2、树的应用:同构树的判断(选做题)
    (1) 问题描述:给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。
    (2) 输入
    输入数据包含多组,每组数据给出2棵二叉树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出”-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。
    示例:
    8
    A 1 2
    B 3 4
    C 5 -
    D - -
    E 6 -
    G 7 -
    F - -
    H - -
    8
    G - 4
    B 7 6
    F - -
    A 5 1
    H - -
    C 0 -
    D - -
    E 2 -
    (3) 输出
    如果两棵树是同构的,输出“Yes”,否则输出“No”。
    示例:
    Yes

    思路:
    /*

    • 不需要记录整棵树的结构
    • 只需要记录某个节点的左右子树即可
    • 比较两棵树是否同构时,在两棵树中找到对应的(data相同)的节点
    • 然后比较左右子树
      */
      结构体:
      struct BiNode {
      char data;//节点数据
      int l, r;//左右子树编号
      }tree_A[N], tree_B[N];
      用tree_A和tree_B两个数组记录两棵树
      For(tree_A[i])
      For(tree_B[j])
      if(tree_A[i].data == tree_B[j])
      判断左右子树是否相同(对应相同或左右互换相同)
    点击查看代码main.cpp
    /*
     * 不需要记录整棵树的结构
     * 只需要记录某个节点的左右子树即可
     * 比较两棵树是否同构时,在两棵树中找到对应的(data相同)的节点
     * 然后比较左右子树
     */
    #include <iostream>
    using namespace std;
    
    const int N = 11;
    bool flag;
    struct BiNode {
        char data;
        int l, r;
    	//构造函数
        BiNode(char x, int lchild, int rchild) {
            data = x;
            l = lchild;
            r = rchild;
        }
        BiNode() { data = l = r = 0; }
    };
    BiNode tree_A[N], tree_B[N];
    
    //判断左右子树互换是否相同
    bool judge(BiNode a, BiNode b) {
        if(tree_A[a.l].data == tree_B[b.l].data && tree_A[a.r].data == tree_B[b.r].data)
            return true;//左右对应
        if(tree_A[a.r].data == tree_B[b.l].data && tree_A[a.l].data == tree_B[b.r].data)
            return true;//左右互换
        return false;
    }
    
    int main()
    {
        int n, m;  char ch, a, b;
        cin >> n;
    	tree_A[0].data = tree_B[0].data = '-';
        for(int i=1; i<=n; ++i) {
            cin >> ch >> a >> b;
            if(a == '-') a=0;
            else    a-='0'-1;
            if(b == '-') b=0;
            else    b-='0'-1;
            tree_A[i] = BiNode(ch, a, b);
        }
        cin >> m;
        for(int i=1; i<=m; ++i) {
            cin >> ch >> a >> b;
            if(a == '-') a=0;
            else    a-='0'-1;
            if(b == '-') b=0;
            else    b-='0'-1;
            tree_B[i] = BiNode(ch, a, b);
        }
    /*
        for(int i=1; i<=n; ++i)
            cout << tree_A[i].data << ' ' << tree_A[i].l << ' ' << tree_A[i].r << endl;
        cout << endl;
        for(int i=1; i<=m; ++i)
            cout << tree_B[i].data << ' ' << tree_B[i].l << ' ' << tree_B[i].r << endl;
    */
        if(n != m) {//节点数不同必定不同构
            cout << "No";
            return 0;
        }
        bool flag = true;//true表示同构
        for(int i=1; i<=n && flag; ++i) {
            for(int j=1; j<=n; ++j) {
                if(tree_A[i].data == tree_B[j].data)//找data相同的节点
                    if(!judge(tree_A[i], tree_B[j])) {
                        flag = false;
                        break;
                    }
            }
        }
        cout << (flag?"Yes":"No");
        return 0;
    }
    
  • 相关阅读:
    【Go】http server 性能测试
    【go】基础
    【Git】gitcongfig 增删改查
    【go】sdk + idea-plugin 开发工具安装
    【Ibatis】总结各种使用技巧
    【nodejs】jade模板入门
    各语言技术列表
    【nodejs】 npm 注意事项
    PAT-l3-002堆栈
    统计相似字符串
  • 原文地址:https://www.cnblogs.com/kuaileyongheng/p/15561029.html
Copyright © 2020-2023  润新知