把二元查找树转变成排序的双向链表…

题目:
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。

 

分析:1、利用二元查找树的特点:左子树上的最大的数是整个左子树最右边的数(这个数是小于根节点的数中最大的数),右子树上最小的数是整个右子树上最左边的数(这个数是大于根节点的数中最小的数)。

      2、虽热不可以创建新的节点,但可以创建指向节点的指针,来记录一些特殊的节点(如左子树的最右节点,右子树的最左节点,父节点等等)位置。

      3、根节点时分为左右两部分处理。左处理部分可以用递归的方法(因为一次处理后形成的子树的根节点的左节点没有右节点,所以可以直接对新子树的根节点的左节点递归左处理),右处理部分也可以用递归的方法,左右两部分类似,是对应的。

 

 

“左处理”大体流程可以是这样的:1、从根节点开始,找到根节点的左子树的最右节点(假设用mark指向),找到以mark为根节点的子树的最左节点(用mark_left指向),用mark_parent指向mark的父节点。

                                2、假如mark就是根节点的左节点,直接将mark的右指针指向根节点即可;否则将mark_left的左指针指向根节点的左节点,mark的右指针指向根节点,根节点的左指针指向mark节点,并将mark_parent的右指针指向NULL。

                                3、终止条件是根节点的左指针为NULL(mark为NULL)。

 

 

下面程序可作为参考:

#include<stdio.h>

typedef struct bi_search_tree   //定义二元查找树节点的数据结构
{
        int value;
        struct bi_search_tree* left;
        struct bi_search_tree* right;
}bi_search_tree;

void tree2link(bi_search_tree*,bi_search_tree**);
void tree2link_left(bi_search_tree*);
void tree2link_right(bi_search_tree*);

int main(int argc,char* argv[])
{
        int i;
        bi_search_tree* link_root;

        bi_search_tree bst[10];
        bi_search_tree* root=bst; //这里手动构造二元查找树有些若,下一篇介绍构造平衡二叉树
        bst[0].value=15;
        bst[1].value=8;
        bst[2].value=20;
        bst[3].value=5;
        bst[4].value=12;
        bst[5].value=18;
        bst[6].value=25;
        bst[7].value=6;
        bst[8].value=11;
        bst[9].value=19;
        bst[0].left=&bst[1];  bst[0].right=bst+2;
        bst[1].left=&bst[3];  bst[1].right=bst+4;
        bst[2].left=&bst[5];  bst[2].right=bst+6;
        bst[3].left=NULL;  bst[3].right=bst+7;
        bst[4].left=&bst[8];  bst[4].right=NULL;
        bst[5].left=NULL;  bst[5].right=bst+9;
        bst[6].left=NULL;  bst[6].right=NULL;
        bst[7].left=NULL;  bst[7].right=NULL;
        bst[8].left=NULL;  bst[8].right=NULL;
        bst[9].left=NULL;  bst[9].right=NULL;

        printf("before translate\n");
        for(i=0;i<10;i++)
        {
                printf("iam=%d ",bst[i].value);
                if(bst[i].left!=NULL)
                        printf("left=%d ",bst[i].left->value);
                else
                        printf("left=NULL ");
                if(bst[i].right!=NULL)
                        printf("right=%d \n",bst[i].right->value);
                else
                        printf("right=NULL \n");

        }
        tree2link(root,&link_root);
        printf("after translate\n");
        bi_search_tree* temp=link_root;
        while(temp!=NULL)
        {
                printf("iam=%d ",temp->value);
                if(temp->left!=NULL)
                        printf("left=%d ",temp->left->value);
                else
                        printf("left=NULL ");
                if(temp->right!=NULL)
                        printf("right=%d \n",temp->right->value);
                else
                        printf("right=NULL \n");
                temp=temp->right;

        }

 

        free(root);

        free(link_root)
        return 0;
}


void tree2link(bi_search_tree* root,bi_search_tree** d_link_root)
{
        tree2link_left(root);
        tree2link_right(root);
        *d_link_root=root;
        while((*d_link_root)->left!=NULL)    //设置双向链表的头指针
                (*d_link_root)=(*d_link_root)->left;
}

void tree2link_left(bi_search_tree* root)
{
        bi_search_tree* mark=root->left;
        bi_search_tree* mark_left;
        bi_search_tree* mark_parent=root->left;
        if(mark!=NULL)
        {
                while((*mark).right!=NULL)      //找左子树的最右节点
                {
                        mark_parent=mark;
                        mark=mark->right;
                }
                mark_left=mark;
                while(mark_left->left!=NULL)   //找mark的最左节点
                        mark_left=mark_left->left;

                if(mark==root->left)
                {
                        mark->right=root;
                }
                else
                {
                        mark_left->left=root->left;
                        mark->right=root;
                        root->left=mark;
                        mark_parent->right=NULL;
                }
                tree2link_left(mark);      //递归,因为mark没有右节点

                free(mark);

                free(mark_left);

                free(mark_parent);
        }
}

void tree2link_right(bi_search_tree* root)
{
        bi_search_tree* mark=root->right;
        bi_search_tree* mark_right;
        bi_search_tree* mark_parent=root->right;

        if(mark!=NULL)
        {
                while(mark->left!=NULL)
                {
                        mark_parent=mark;
                        mark=mark->left;
                }
                mark_right=mark;
                while(mark_right->right!=NULL)

                        mark_right=mark_right->right;

                if(root->right==mark)
                        mark->left=root;
                else
                {
                        mark_right->right=root->right;
                        mark->left=root;
                        root->right=mark;
                        mark_parent->left=NULL;
                }
                tree2link_right(mark);

                free(mark);

                free(mark_right);

                free(mark_parent);
        }
}

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值