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;
}
posted @ 2021-11-16 14:11  快乐永恒  阅读(157)  评论(0编辑  收藏  举报