• 剑指OFFER之二叉搜索树与双向链表(九度OJ1503)


    题目描述:

    输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

     

    输入:

    输入可能包含多个测试样例。
    对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数。
    接下来的n行,每行为一个二叉搜索树的先序遍历序列,其中左右子树若为空则用0代替。

     

    输出:

    对应每个测试案例,
    输出将二叉搜索树转换成排序的双向链表后,从链表头至链表尾的遍历结果。

     

    样例输入:
    1
    2 1 0 0 3 0 0
    样例输出:
    1 2 3

    解题思路:

      这道题应该是最近写的最繁琐的一道题了。

      首先输入按规则来,需要进行前序遍历输入

    void createTree(BTree **b){  
        int m;
        scanf("%d",&m);
        if(m == 0)
            *b = NULL;
        else{
            BTree *s = (BTree *)malloc(sizeof(BTree));
            s->data = m;
            s->lchild = NULL;
            s->rchild = NULL;
            *b = s;
            createTree(&((*b)->lchild));
            createTree(&((*b)->rchild));
        }
    }

      另外,整体的思路,是用一个指针记录转换的双链表表尾。

      每次进行中序遍历的转换。

      最先转换的是最左下的节点,

    void converNode(BTree *b,BTree **p){
        if(b == NULL)
            return ;
        BTree *pnow = b;
        if(b->lchild != NULL)
            converNode(b->lchild,p);
        
        pnow->lchild = *p;
        if(*p != NULL)
            (*p)->rchild = pnow;
    
        *p = pnow;
    
        if(b->rchild != NULL)
            converNode(b->rchild,p);
    }

      每次遍历节点的左孩子右孩子。把左孩子指向转换链表的尾节点,并把末尾指针的右孩子指向自己。右孩子指向节点的右孩子。如果没有右孩子就返回。下面是代码思路的步骤:

    1 找到最左边也就是最小的节点,PLast = NULL;

    2 让节点的左孩子指向链尾,然后链尾指针右移。如果右孩子为空就返回。

    最后我们从尾遍历回头指针返回。

    全部代码:

    #include <stdio.h>
    #include <stdlib.h>
    typedef struct btree{
        int data;
        struct btree *lchild,*rchild;
    }BTree;
     
    void createTree(BTree **b);
    void inorderTree(BTree *b);
    BTree * convert(BTree *b);
    void converNode(BTree *b,BTree **p);
     
    int main(){
        int n;
        scanf("%d",&n);
        while(n--){
            BTree *b = (BTree *)malloc(sizeof(BTree));   
            createTree(&b);
            BTree *head = convert(b);
            while(head!=NULL){
                printf("%d ",head->data);
                head = head->rchild;
            }
            printf("
    ");
        }
        return 0;
    }
    BTree* convert(BTree *b){
        BTree *pLast = NULL;
        converNode(b,&pLast);
     
        BTree *phead = pLast;
        while(phead != NULL && phead->lchild != NULL)
            phead = phead->lchild;
        return phead;
    }
    void converNode(BTree *b,BTree **p){
        if(b == NULL)
            return ;
        BTree *pnow = b;
        if(b->lchild != NULL)
            converNode(b->lchild,p);
         
        pnow->lchild = *p;
        if(*p != NULL)
            (*p)->rchild = pnow;
     
        *p = pnow;
     
        if(b->rchild != NULL)
            converNode(b->rchild,p);
    }
    void createTree(BTree **b){  
        int m;
        scanf("%d",&m);
        if(m == 0)
            *b = NULL;
        else{
            BTree *s = (BTree *)malloc(sizeof(BTree));
            s->data = m;
            s->lchild = NULL;
            s->rchild = NULL;
            *b = s;
            createTree(&((*b)->lchild));
            createTree(&((*b)->rchild));
        }
    }
    /**************************************************************
        Problem: 1503
        User: xhalo
        Language: C
        Result: Accepted
        Time:80 ms
        Memory:1704 kb
    ****************************************************************/
  • 相关阅读:
    Windows 下搭建Android开发环境
    浅谈C/C++中运算符的优先级、运算符的结合性以及操作数的求值顺序
    更新Android SDK到3.0版本时,遇到Failed to rename directory E:\android\tools to E:\android\temp\ToolPackage.old01问题
    单词计数 soj1076
    拓扑排序
    浅谈C和C++中的const关键字
    快速排序
    拓扑排序 soj1075
    集合划分问题
    浅谈C/C++中的顺序点和副作用
  • 原文地址:https://www.cnblogs.com/xing901022/p/3781713.html
Copyright © 2020-2023  润新知