2018.5.23(二叉树-中序遍历中查找某一结点的后继结点)

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;

struct Tree
{
    int data;
    Tree *parent;//存储某一结点的父结点
    Tree *left,*right;
};

Tree *Insert(Tree *root,const int node)//插入元素,使其符合二叉树的结构
{
    Tree *parent_point,*current_point;
    Tree *new_point;

    new_point=(Tree*)malloc(sizeof(Tree));//新开辟一块new_point的空间,使其left,right,parent都指向NULL
    new_point->data=node;
    new_point->parent=NULL;
    new_point->left=NULL;
    new_point->right=NULL;

    if(root==NULL)
        return new_point;

    current_point=root;
    while(current_point!=NULL)
    {
        parent_point=current_point;

        current_point=(node>current_point->data)?current_point->right:current_point->left;//判断某一数值该放到当前结点的左子树上还是该结点的右子树上
    }
    if(node>parent_point->data)
    {
        parent_point->right=new_point;
        new_point->parent=parent_point;
    }
    else
    {
        parent_point->left=new_point;
        new_point->parent=parent_point;
    }

    return root;
}

Tree *Create(const int *node,const int len)
{
    Tree *root=NULL;

    for(int i=1;i<=len;i++)
        root=Insert(root,node[i]);

    return root;
}

Tree *Find(Tree *node,int num)//查找结点位置
{
    while(node!=NULL&&node->data!=num)//node!=NULL一定要在node->data!=num前,如果在其后,当node==NULL时,node->data就是非法调用,会出错
        node=(num>node->data)?node->right:node->left;//有二叉树的结构可知,左子树的值都小于其父结点,右子树的值都大于其父结点,故只需判断num与node->data的相对大小,如果num大,则node向其右子树方向去,反之,向其左子树方向去

    return node;
}

void Solve(Tree *node)//查找后继元素
{
    printf("%d->",node->data);

    if(node->right!=NULL)//如果需查找的结点存在右子树
    {
        node=node->right;
        while(node!=NULL&&node->left!=NULL)//查找当前节点右子树最左端的结点
            node=node->left;

        if(node!=NULL)
            printf("%d\n",node->data);
        else
            printf("NULL\n");
        return ;
    }

    if(node->right==NULL)//如果需查找的结点不存在右子树
    {
        while(node->parent->left!=node)//判断当前结点的父节点的左子树是否等于当前结点;
        {
            node=node->parent;//如果没找到满足条件的结点,当前结点指向其父节点
            if(node->parent==NULL)//如果便利到根节点也没有找到其后继结点,说明其需查找的结点不存在后继结点,返回NULL;
            {
                printf("NULL\n");
                return ;
            }
        }

        printf("%d\n",node->parent->data);//如果while()中未执行printf("NULL\n");语句,说明其存在后继结点,打印出找到结点的父节点
        return ;
    }
}

void print(Tree *root)
{
    if(root!=NULL)
    {
        print(root->left);
        printf("%d ",root->data);
        print(root->right);
    }
}

int main()
{
    Tree *root;
    int n;

    printf("Input n:\n");
    while(cin>>n)
    {
        if(n==0)
            break;

        int node[n+1];

        printf("\nInput %d numbers\n",n);
        for(int i=1;i<=n;i++)
            scanf("%d",&node[i]);

        root=Create(node,n);
        printf("***中序遍历***\n");
        print(root);
        printf("\n");

        int num;
        printf("\nInput some numbers:\n");
        while(cin>>num)
        {
            if(num==0)
                break;

            Tree *find_num=Find(root,num);

            if(find_num==0)
                printf("No Find!\n");
            else
                Solve(find_num);
        }
        printf("\nInput n:\n");
    }
    return 0;
}

查找后继元素解析:
当n=9时
9个数分别为6,3,8,5,2,9,4,7,10;
其树形结构为:

这里写图片描述
中序遍历结果为:2,3,4,5,6,7,8,9,10
如何查找某一节点的后继元素?
思路:
当某一结点存在右子树时,其后继结点为其右子树上最左的结点,例如元素3的后继节点为其右子树(元素5)最左的结点(元素4),故3的后继结点为4;
当某一结点不存在右子树时,其后继结点为第一个当前结点的父结点的左子树与当前结点相等的结点的父结点,例如,若查找元素5的后继结点,先判断其是否存在右子树,结果为不存在,去找此结点的父结点,为元素3,判断当前结点(元素5)的父节点的左子树元素2)是否与当前结点(元素5)相同,,继续向上找,当前结点来到元素5的父节点元素3位置,判断当前结点(元素3)的父节点的左子树元素3)是否为当前结点(元素3)的结点,,故第一个满足条件的结点为元素3,其父节点为元素6,故元素5的后继结点为元素6;

猜你喜欢

转载自blog.csdn.net/Violet_ljp/article/details/80425134
今日推荐