zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    codevs 1115 开心的金明
    POJ 1125 Stockbroker Grapevine
    POJ 2421 constructing roads
    codevs 1390 回文平方数 USACO
    codevs 1131 统计单词数 2011年NOIP全国联赛普及组
    codevs 1313 质因数分解
    洛谷 绕钉子的长绳子
    洛谷 P1276 校门外的树(增强版)
    codevs 2627 村村通
    codevs 1191 数轴染色
  • 原文地址:https://www.cnblogs.com/kuaileyongheng/p/15561029.html
Copyright © 2011-2022 走看看