浙大数据结构第三周之03-树3 Tree Traversals Again

题目详情:

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.

浙大数据结构第三周之03-树3 Tree Traversals Again_第1张图片


Figure 1

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顺序就是原二叉树的前序遍历结果,pop出的顺序就是原二叉树的中序遍历结果

另外,本题节点编号是从1~N,所以在利用中序和前序构造二叉树时要注意传递的实参是分割preorder数组和inorder数组的下标,函数递归返回的是下标对应的值

递归的终止条件不仅有分割起点和终点相等,还有分割起点大于分割终点这种情况,这时要返回空节点

代码实现:

/*
1.实现堆栈的数据结构
2.建树
Push入的顺序是前序遍历
Pop出的顺序是后序遍历
3.后序遍历打印
*/
#include 
#include 
#define MAX_SIZE 35
#define PUSH "Push"
#define POP "Pop"
#define NONE -1
/*实现堆栈的数据结构*/ 
typedef struct Stack Stack;
struct Stack {
    int Data[MAX_SIZE];
    int Rear;
};
void Init(Stack* stackName) {
    (*stackName).Rear = -1;
    return;
}
bool IsEmpty(Stack* stackName) {
    if((*stackName).Rear == -1) return true;
    else return false;
}
bool IsFull(Stack* stackName) {
    if((*stackName).Rear == MAX_SIZE - 1) return true;
    else return false;
}
void Push(Stack* stackName, int data) {
    if(IsFull(stackName)) return;
    (*stackName).Data[++(*stackName).Rear] = data;
    return;
}
void Pop(Stack* stackName) {
    if(IsEmpty(stackName)) return;
    (*stackName).Rear--;
    return;
}
int Top(Stack* stackName) {
    if(IsEmpty(stackName)) return NONE;
    return (*stackName).Data[(*stackName).Rear];
}

/*建树*/
typedef struct Tree Tree;
struct Tree {
    int LeftChild, RightChild;
    bool IsRoot;
};
Tree tree[MAX_SIZE];
int Preorder[MAX_SIZE];
int Inorder[MAX_SIZE];
int N;
void GetTraversal() {
    Stack stack;
    Init(&stack);
    scanf("%d", &N);
    getchar();
    int preCount = 0;
    int inCount = 0;
    int loop = N * 2;
    for(int i = 0; i < loop; i++) {
        char string[4];
        scanf("%s", string);
        if(string[1] == 'u') {
            int data;
            scanf("%d", &data);
            Push(&stack, data);
            Preorder[preCount++] = data;
        }
        if(string[1] == 'o') {
            int data = Top(&stack);
            Pop(&stack);
            Inorder[inCount++] = data;
        }
    }
    for(int i = 1; i <= N; i++) {
        tree[i].IsRoot = true;
        tree[i].LeftChild = NONE;
        tree[i].RightChild = NONE;  
    }
    return;
}
int BuildTreeTraversal(int preStart, int preEnd, int inStart, int inEnd) {
    if(preStart == preEnd) return Preorder[preEnd];
    if(preStart > preEnd) return NONE; //这个说明是遍历到空节点

    int root = Preorder[preStart];
    int cuttingLine = 0;
    for(int i = 0; i < N; i++) {
        if(Inorder[i] == root) {
            cuttingLine = i;
            break;
        }
    }
    int leftSubtree = (cuttingLine - 1) - inStart + 1;
    int rightSubtree = inEnd - (cuttingLine + 1) + 1; 
    tree[root].LeftChild = BuildTreeTraversal(preStart + 1, preStart + leftSubtree, inStart, cuttingLine - 1);
    tree[root].RightChild = BuildTreeTraversal(preStart + leftSubtree + 1, preEnd, cuttingLine + 1, inEnd);
    return root;
}
void PostPrint(int root) {
    if(root == NONE) return;
    
    PostPrint(tree[root].LeftChild);
    PostPrint(tree[root].RightChild);
    if(--N) printf("%d ", root);
    else printf("%d", root);
    return;
}
int main() {
    GetTraversal();
    int root = BuildTreeTraversal(0, N - 1, 0, N - 1);
    PostPrint(root);
    return 0;
}

你可能感兴趣的:(数据结构,数据结构)