icoding复习5 树 感觉难度巨大....

icoding 复习5 

1. 先序遍历 
已知二叉树按照二叉链表方式存储,利用栈的基本操作写出先序遍历非递归形式的算法:
void pre_order(BiTree root);
二叉树的相关定义如下:
typedef int DataType;
typedef struct Node{
    DataType data;
    struct Node* left;
    struct Node* right;
}BiTNode, *BiTree;
遍历所使用栈的相关操作如下:
#define Stack_Size 50
typedef BiTNode* ElemType;
typedef struct{
    ElemType elem[Stack_Size];
    //BiTNode*  elem[Stack_Size]
    int top;
}Stack;
void init_stack(Stack *S); // 初始化栈
bool push(Stack* S, ElemType x); //x 入栈
bool pop(Stack* S, ElemType *px); //出栈,元素保存到px所指的单元,函数返回true,栈为空时返回 false
bool top(Stack* S, ElemType *px); //获取栈顶元素,将其保存到px所指的单元,函数返回true,栈满时返回 false
bool is_empty(Stack* S);  // 栈为空时返回 true,否则返回 false
在遍历过程中,pre_order函数需要调用 visit_node 函数来实现对结点的访问,该函数声明如下:
void visit_node(BiTNode *node);
#include
#include
#include "bitree.h" //请不要删除,否则检查不通过

大概率考原题和改编!!!!!! 

void pre_order(BiTree root){
    if(!root) return;
    Stack *S;
    
    BiTNode *p;
    
    init_stack(S);
    push(S, root->data);
    while(!is_empty(S)){
        pop(S, &p);
        visit_node(p);
        
        if(p->left)
            push(S, p->left);
        if(p->right){
            push(S, p->right);
        }
    } 
}
//解法2, 声明为Stack S; 
void pre_order(BiTree root)
{
    Stack S;
    BiTNode *p, *q;

    //    S.top = -1; 初始化应该会赋值
    p = root;
    init_stack(&S);

    if (p == NULL)
        return;
    do {
        if (p) {
            visit_node(p);//先序遍历的核心,先访问根节点 
            push(&S, p);
            p = p->left;
        } else {
            pop(&S, &p);
            p = p->right;
        }
    } while (p || !(is_empty(&S)));
}

//中序遍历
void InOrder(BiTNode *root){
    Stack *S; BiTNode *p;
    init_stack(S);
    if(!root ) return;
    while(p || !is_empty(S)){
        while(p){
            push(S, p);
            p = p->left;
        }
        if(!is_empty(S)){
            pop(S, &p);
            visit_node(p);
            p = p->right;
        }
    }

//后序遍历非递归 难 
void PostOrder(BiTNode *root){
    Stack *S; BiTNode *p, *r; bool flag;
    init_stack(S);
    p = root;
    do{
        while(p){
            push(S, p);
            p = p->left;
        }
        r = NULL;
        flag = true;
        
        while(!is_empty(S) && flag){
            top(S, &p);
            if(p->right == r){
                visit_node(p);
                pop(S, &p);
                r = p;
            }
            else{
                p = p->right;
                flag = false;
            }
        }
    }while(!is_empty(S));

2. 路径 
假设二叉树采用二叉链表方式存储, root指向根结点,node 指向二叉树中的一个结点,
编写函数 path,计算root到 node 之间的路径,(该路径包括root结点和 node 结点)。path 函数声明如下:
bool path(BiTNode* root, BiTNode* node, Stack* s);
其中,root指向二叉树的根结点,node指向二叉树中的另一结点,s 为已经初始化好的栈,
该栈用来保存函数所计算的路径,如正确找出路径,则函数返回 true,此时root在栈底,node在栈顶;

#include "bitree.h" //请不要删除,否则检查不通过
#include
#include

bool path(BiTNode* root, BiTNode* node, Stack* s){
    BiTNode *p, *q;
    
    if(!root || !node)    return false;
    p = root;
    if(p == node){
        push(s, p);
        return true;
    }
    
    while(p || !is_empty(s)){
        while(p){//先压入再判断 
            push(s, p);
            if(p == node)
                return true;
            
            p = p->left;
        }
        top(s, &p);
        if(p->right == q || p->right == NULL){
            q = p;
            top(s, &p);
            p = NULL;
        }
        else
            p = p->right;
    }
    return true;
}


3. 共同祖先
假设二叉树采用二叉链表方式存储, root指向根结点,p所指结点和q所指结点为二叉树中的两个结点,
编写一个计算它们的最近的共同祖先,函数定义如下:
BiTNode * nearest_ancestor(BiTree root, BiTNode *p, BiTNode *q);
其中 root 指向二叉树的根结点,p 和 q 分别指向二叉树中的两个结点。
提示:在完成本题时,可利用 path 函数获取p和q两个结点到根结点之间的路径,
之后再计算两条公共路径得出最近的共同祖先。path函数及栈相关定义如下:


#include
#include
#include "bitree.h" //请不要删除,否则检查不通过

BiTNode * nearest_ancestor(BiTree root, BiTNode *p, BiTNode *q){
    if(!root || !p || !q) return NULL;
    Stack *s1, *s2;
    init_stack(s1); init_stack(s2);
    path(root, p, s1);
    path(root, q, s2);
    for(int i = 0; s1->elem[i] == s2->elem[i]; i++) 
        ;
    return s1->elem[i-1];

4. 树转二叉树
使用队列,编写transfrom函数,将普通树转换成对应的二叉树。二叉树的相关定义如下:
typedef int DataType;
typedef struct Node{
    DataType data;
    struct Node* left;
    struct Node* right;
}BiTNode, *BiTree;

普通树节点 的定义如下:
#define MAX_CHILDREN_NUM 5
struct _CSNode
{
    DataType data;
    struct _CSNode *children[MAX_CHILDREN_NUM];
};
typedef struct _CSNode CSNode;
其中,子树的根节点的指针存放在children数组的前k个元素中,即如果children[i]的值为NULL,
而children[i-1]不为NULL,则表明该结点只有i棵子树,子树根结点分别保存在children[0]至children[i-1]中。
队列相关定义及操作如下:
struct __Queue
{
    int i, j; //指向数组内元素的游标
    void **array;//这个就是提示!!!!!!!!!!!!!!!!!!!!!!!!!!! 
};
typedef struct __Queue Queue;

Queue* create_queue(); //创建队列
bool is_empty_queue(Queue *tree); //队为空返回true,不为空时返回false
void* del_queue(Queue *tree); //结点指针出队
void add_queue(Queue *tree, void *node); //结点指针入队
void free_queue(Queue *tree); //释放队列
transform函数定义如下:

BiTNode* transform(CSNode *root);
其中 root 为普通树的根结点,函数返回该树对应二叉树的根结点。


#include
#include
#include "bitree.h" //请不要删除,否则检查不通过 
 
BiTNode* transform(CSNode *root){
    if(!root) return NULL;
    
    Queue *que, *bque;
    
    BiTNode *p;
    //二叉树根结点创立 
    //小心点, 记得分配空间 
    //为什么想到建立二叉树结点?
    //普通树结点和二叉树结点无法强制类型转换 
    p = (BiTNode *)malloc(sizeof(struct Node));
    p->data = root->data;
    p->left = p->right = NULL;
     
    
    que = create_queue();
    bque = create_queue();
    //建立双队目的在于建立有序二叉结点序列 
    add_queue(que, root);
    add_queue(bque, p);
    
    //注意这个while怎么处理好孩子与孙子关系的, 没用递归!!! 
    while(!is_empty_queue(que)){
        BiTree bq;//创建二叉树队列头结点(根结点) 
        bq = del_queue(bque);
        CSNode *q;
        q = del_queue(que);
        //第一次执行该操作就相当于建立了二叉树的根
        
        int i = 0; 
        BiTNode *former = NULL;
        
        for(i = 0; i < MAX_CHILDREN_NUM; i++){
            if(q->children[i]){//判存在 
                BiTNode *bnode = (BiTNode *)malloc(sizeof(struct Node));
                bnode->data = q->children[i]->data;
                bnode->left = bnode->right = NULL; 
        
                //放置结点位置
                if(i == 0){
                    bq->left = bnode;
                }
                else{//兄弟变为孩子了可怜 
                    former->right = bnode;
                }
                former= bnode;
                 
                add_queue(bque, bnode);
                add_queue(que, q->children[i]);
            }
        }     
    }
    free(que->array);
    free(que);
    free(bque->array);
    free(bque);
    
    return p;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

风起风里

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

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

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

打赏作者

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

抵扣说明:

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

余额充值