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
//棧基本實現
#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
/*
 * 都在書上有
 * 非遞歸算法可以用棧模擬遞歸(不過課本上不是這麼寫的)
 */
#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章