数据结构(陈越 、何钦铭)--第三周编程作业

03-树1 树的同构 (25分)

给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。
图1
图2
现给定两棵树,请你判断它们是否是同构的。

输入格式:
输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:
如果两棵树是同构的,输出“Yes”,否则输出“No”。

输入样例1(对应图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 -

输出样例1:
Yes

输入样例2(对应图2):
8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4

输出样例2:
No

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define Null -1
struct node
{
    char ele;
    int left;
    int right;
}t1[MAXSIZE], t2[MAXSIZE];

int creatTree(struct node t[]);
int judgeIs(int root1, int root2);

int main(){

    //构建二叉树
    int root1 = creatTree(t1);
    int root2 = creatTree(t2);

    //判断两棵树是否同构
    if(judgeIs(root1, root2)){
        printf("Yes");
    }else{
        printf("No");
    }
    return 0;
}

int creatTree(struct node t[]){
    int m;
    scanf("%d", &m);
    if(m){
        int check[MAXSIZE];
        for(int i = 0; i < m; i++)  check[i] = 0;
        for(int i = 0; i < m; i++){

            char leftchar;
            char rightchar;
            scanf("\n%c %c %c", &t[i].ele, &leftchar, &rightchar);
            if(leftchar != '-'){
                t[i].left = leftchar - '0';
                check[t[i].left] = 1;
            }else{
                t[i].left = Null;
            }
            if(rightchar != '-'){
                t[i].right = rightchar - '0';
                check[t[i].right] = 1;
            }else{
                t[i].right = Null;
            }
        }

        for(int i = 0; i < m; i++){
            if(check[i] == 0)
                return i;
        }
    }

    return Null;
}

int judgeIs(int root1, int root2){

    //两个都是空的,认为是同构的
    if(root1 == Null && root2 == Null){
        return 1;
    }
    //一个是空的,一个不空
    if((root1 == Null && root2 != Null) || (root2 == Null && root1 != Null)){
        return 0;
    }
    //根就不一样
    if(t1[root1].ele != t2[root2].ele)  return 0;
    //根的左边空,右边判断
    if((t1[root1].left == Null) && (t2[root2].left == Null))
        return judgeIs(t1[root1].right, t2[root2].right);
    //根的右边空,左边判断
    if((t1[root1].right == Null) && (t2[root2].right == Null))
        return judgeIs(t1[root1].left, t2[root2].left);
    //一边是一样的
    if(((t1[root1].left != Null) && (t2[root2].left != Null)) &&
        (t1[t1[root1].left].ele == t1[t2[root2].left].ele))
        return (judgeIs(t1[root1].left, t2[root2].left) &&
                judgeIs(t1[root1].right, t2[root2].right));
    //左右两边相反的
    else{
        return (judgeIs(t1[root1].left, t2[root2].right) &&
                judgeIs(t1[root1].right, t2[root2].left));
    }
}

03-树2 List Leaves (25分)

Given a tree, you are supposed to list all the leaves in the order of top down, and left to right.

Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree – and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a “-” will be put at the position. Any pair of children are separated by a space.

Output Specification:
For each test case, print in one line all the leaves’ indices in the order of top down, and left to right. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.

Sample Input:

8
1-
0 -
2 7
__
__
5 -
4 6
Sample Output:
4 1 5

#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 10
#define Tree int
#define Null -1

typedef struct TreeNode
{
    Tree Left;
    Tree Right;
}TREENODDE;
TREENODDE T[MAX_SIZE];

struct Node
{
    Tree Data;
    struct Node *Next;
};
struct QNode
{
    struct Node *rear;
    struct Node *front;
};
typedef struct QNode *Queue;

Tree BuildTree(TREENODDE T[], int N);
void OutputLeaves(Tree Root, TREENODDE T[]);

Queue CreatQueue();
void AddQ(Queue Q, int item);
int DeleteQ(Queue Q);

int main()
{
    Tree Root;
    int N;

    scanf("%d", &N);
    if(!N){
        return 0;
    }

    Root = BuildTree(T, N);
    OutputLeaves(Root,T);

    return 0;
}

Tree BuildTree(TREENODDE T[], int N)
{
    int i, check[MAX_SIZE];
    char cl, cr;

    if(N)
    {
        for(i = 0; i < N; i++)
            check[i] = 0;
        for(i = 0; i < N; i++)
        {
            scanf("\n%c %c", &cl, &cr);
            if(cl != '-')
            {
                T[i].Left = cl - '0';
                check[T[i].Left] = 1;
            }
            else
                T[i].Left = Null;
            if(cr != '-')
            {
                T[i].Right = cr - '0';
                check[T[i].Right] = 1;
            }
            else
                T[i].Right = Null;

        }
    }
    for(i = 0; i < N; i++)
    {
        if(!check[i])
            break;
    }
    return i;
}

void OutputLeaves(Tree Root, TREENODDE T[])
{
    int t, flag = 0;
    Queue Q;
    Q = CreatQueue();
    if((T[Root].Left == Null) && (T[Root].Right == Null)){
        printf("%d", Root);
        return;
    }
    AddQ(Q, Root);
    while(Q->front != NULL)
    {
        t = DeleteQ(Q);
        if((T[t].Left == Null) && (T[t].Right == Null))
        {
            if(flag)
                printf(" ");
            printf("%d", t);
            flag = 1;
        }
        if(T[t].Left != Null)
            AddQ(Q, T[t].Left);
        if(T[t].Right != Null)
            AddQ(Q, T[t].Right);
    }
    free(Q);
}

Queue CreatQueue()
{
    Queue Q;
    Q = (Queue)malloc(sizeof(struct QNode));
    Q->front = NULL;
    Q->rear = NULL;
    return Q;
}

void AddQ(Queue Q, int item)
{
    struct Node *s;
    s = (struct Node*)malloc(sizeof(struct Node));
    s->Data = item;  s->Next = NULL;

    /*看添加的节点是不是第一个节点*/
    if(Q->front == NULL)
    {
        Q->front = s;
        Q->rear = s;
    }
    else
    {
        Q->rear->Next = s;
        Q->rear = s;
    }
}

/*如果Q为空,返回Null,即-1*/
int DeleteQ(Queue Q)
{
    int s;
    struct Node *item;
    if(Q->front == NULL)
    {
        return Null;
    }
    else
    {
        s = Q->front->Data;
        item = Q->front;
        Q->front = Q->front->Next;
        free(item);
    }
    return s;
}

之后我又写了个简单的

#include <stdio.h>
#define MAXSIZE 10
#define Null -1

struct node{
    int left;
    int right;
}T[MAXSIZE];

struct quence
{
    int data[MAXSIZE];
    int head;
    int size;
}Q;


//Create the tree; Return the root
int creatTree(struct node T[], int n);
void printResult(int n, int root);

int main(){

    int root;
    int n;
    scanf("%d", &n);
    Q.size = 0; Q.head = -1;

    //Create the tree
    root = creatTree(T, n);

    //make the quence and print the result
    printResult(n, root);

    //Print the result
    return 0;
}

void printResult(int n, int root){
    int printFlag = 0;
    //初始化队列,将第一个加进去
    Q.data[0] = root;
    Q.head++;
    Q.size++;

    //While the quence is not empty
    while (Q.size != 0)
    {
        //pop
        int popnumber = Q.data[Q.head];

        if((T[popnumber].left == Null) &&
            (T[popnumber].right == Null)){
            if(printFlag)   printf(" ");
            printf("%d", popnumber);
            printFlag = 1;
        }

        Q.head++;
        Q.size--;

        //push
        if(T[popnumber].left != Null){
            
            Q.data[Q.head + Q.size] = T[popnumber].left;
            Q.size++;
        }
        if(T[popnumber].right != Null){
            
            Q.data[Q.head + Q.size] = T[popnumber].right;
            Q.size++;
        }
    }
    
}

int creatTree(struct node T[], int n){
    int root = Null;
    int check[MAXSIZE];
    if(n){
        for(int i = 0; i < n; i++)  check[i] = 0;
        for(int i = 0; i < n; i++){
            char cl;
            char cr;
            scanf("\n%c %c", &cl, &cr);

            //cl
            if(cl != '-'){
                T[i].left = cl - '0';
                check[T[i].left] = 1;
            }else{
                T[i].left = Null;
            }
            //cr
            if(cr != '-'){
                T[i].right = cr - '0';
                check[T[i].right] = 1;
            }else{
                T[i].right = Null;
            }
        }
        for(int i = 0; i < n; i++){
            if(check[i] == 0){
                root = i;
                break;
            }
        }
        return root;
    }

    return Null;
}

03-树3 Tree Traversals Again (25分)

An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.
在这里插入图片描述
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: “Push X” where X is the index of the node being pushed onto the stack; or “Pop” meaning to pop one node from the stack.

Output Specification:
For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:
6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop

Sample Output:
3 4 2 6 5 1

/*
一,程序的思路如下:
    堆栈输入实际上包含了两种二叉树的遍历方法,即前序遍历和中序遍历
    Push是前序,即1 2 3 4 5 6
    Pop是中序,即3 2 4 1 6 5
    而我们要做到就是已知两种遍历求后序遍历的情况
    方法就不细说了前序第一个元素就是根节点,从中序序列中找到根节点,之前的就是左子树,之后的就是右子树,对左右子树进行递归循环即可
二。实际上本题用C++语言来编写简单好看,但本人还没学习C++,所以程序较为繁琐
    但其实,只要理解了题目到底要干什么,对遍历操作有基本的认识,就可以做题了
*/
#include <stdio.h>
#include <string.h>
#define MAXSIZESTR 4
#define MAXSIZE 30

int flag = 0;
void PrintPost(int Preorder[], int Inorder[], int N);

int main()
{

    int N, Preorder[MAXSIZE], PreorderT[MAXSIZE], Inorder[MAXSIZE];
    char str[MAXSIZESTR + 1];   int item;
    int i, Prei = 0, Ini = 0, PreiT = 0;

    scanf("%d", &N);
    if(N)
    {
        for(i = 0; i < 2*N; i++)
        {
            scanf("\n%s", str);
            if(strcmp(str, "Push") == 0)
            {
                scanf(" %d", &item);
                Preorder[Prei++] = item;
                PreorderT[PreiT++] = item;
            }
            else
            {
                Inorder[Ini++] = PreorderT[--PreiT];
            }
        }
    }

    PrintPost(Preorder, Inorder, N);

    return 0;
}

void PrintPost(int Preorder[], int Inorder[], int N)
{
    int Root, i, j;
    int P[MAXSIZE], I[MAXSIZE];
    if(N)
    {
        for(i = 0; i < N; i++)
    {
        P[i] = Preorder[i];
        I[i] = Inorder[i];
    }
    int Pleft[MAXSIZE], Ileft[MAXSIZE], Nleft;
    int Pright[MAXSIZE], Iright[MAXSIZE], Nright;
    Root = P[0];
    for(i = 0; i < N; i++)
    {
        if(I[i] == Root)
        {
            break;
        }
    }
    Nleft = i;  Nright = N-i-1;
    for(j = 0; j < Nleft; j++)
    {
        Pleft[j] = P[j+1];
        Ileft[j] = I[j];
    }
    for(j = 0; j < Nright; j++)
    {
        Pright[j] = P[j + Nleft + 1];
        Iright[j] = I[j + Nleft + 1];
    }
    PrintPost(Pleft, Ileft, Nleft);
    PrintPost(Pright, Iright, Nright);
    if(flag)
    {
        printf(" ");
    }
    printf("%d", Root);
    flag = 1;
    }
    return;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

比巧克力巧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值