标题:这么多天了,搜索二叉树才搞定了最基础的部分(蹉跎了好些岁月,终于搞定了 ...
只看楼主
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
得分:0 
回复 9楼 renkejun1942
我以为你是写给自己以后看(甚至于使用)的。。。

φ(゜▽゜*)♪
2017-05-10 12:33
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 10楼 书生牛犊
这个啊,你看看置顶贴那个通用链表呢?

二叉树基础,弄那么复杂没有必要。
通用性的问题,那是运用部分,先缓缓。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-10 12:33
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
突然明白删除节点原理了~二叉搜索树的一个重要性质就是左边的节点全都比原数小~右边的节点全都比原数大~所以搞明白了就是寻找右子树的最小值作为替身就行了~搞明白了原来高估其复杂性了~其实我以前写了一个~不过有点问题~删除节点的时候竟然把那节点以下的所有元素都弄丢了~汗啊~~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-05-10 12:47
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
就是这个番薯代码~对着注释敲的~不知道删除节点哪里出问题了~竟然删除后把节点下面的元素都弄丢了~~~有时间可以帮忙看看~

程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<conio.h>

struct node  
{
    int value;

    struct node* left;
    struct node* right;
};

typedef struct node NODE;
typedef struct node* PNODE;

void menu();                          //菜单

int my_scanf();                       //输入函数

void new_node(PNODE* n,int value);    //创造一个新节点

void free_node(PNODE* n);             //释放节点

void free_tree(PNODE* n);             //释放二叉树

PNODE find_node(PNODE n,int value);   //查找节点

void insert_node(PNODE* n,int value); //插入节点 

int get_max_depth(PNODE n);           //最长位置

int get_min_depth(PNODE n);           //最短位置

int get_num_nodes(PNODE n);           //获取节点数目

int get_min_value(PNODE n);           //最短路径长度

int get_max_value(PNODE n);           //最长路径长度

void deletenode(PNODE* n);             //删除节点

void delete_node(PNODE* n,int value);  

void pre_order_traversal(PNODE n);     //前序遍历

void in_order_traversal(PNODE n);      //中序遍历

void post_order_traversal(PNODE n);    //后序遍历

int main()
{
    int option=0;

    PNODE tree=NULL;
    PNODE node=NULL;

    while (1)
    {
        system("cls");

        menu();

        option=my_scanf();

        puts("---------------------------------");

    if (option<0||option>11)
    {    
         fprintf(stderr,"invalid option\n");
         system("pause");

         continue ;
    }


        switch (option)
        {
            case 0:

                exit(0);

            case 1:

                printf("Enter number to inserrt:");

                option=my_scanf();

                puts("\n");

                insert_node(&tree,option);

                break;

            case 2:

                printf("Enter number to delete:");

                option=my_scanf();

                puts("\n");

                delete_node(&tree,option);

                break;

            case 3:

                printf("Enter number to find");

                option=my_scanf();

                puts("\n");

                node=find_node(tree,option);

                if (node!=NULL)
                    puts("Found node\n");
                else
                    puts("Couldn't find node\n");

                break;

            case 4:

                puts("Pre order traversal:");

                pre_order_traversal(tree);

                puts("\n");

                break;


            default :

                break;

            case 5:

                puts("In order traversal:");

                in_order_traversal(tree);

                puts("\n");

                break;

            case 6:

                puts("Post order traversal:");

                post_order_traversal(tree);

                puts("\n");

                break;

            case 7:

                printf("Max depth is %i\n\n",get_max_depth(tree));

                break;

            case 8:

                printf("Min depth is %i\n\n",    get_min_depth(tree));

                break;

            case 9:

                printf("Max value is %i\n\n",get_max_value(tree));

                break;

            case 10:

                printf("Min value is %i\n\n",get_min_value(tree));

                break;

            case 11:

                printf("Node Count is %i\n\n",get_num_nodes(tree));

                break;

        }

        system("pause");

    }

    return 0;
}

void menu()
{
    puts("---------------------------------");
    puts("0 Exit");
    puts("1 Insert node");
    puts("2 Delete node");
    puts("3 Find node");
    puts("4 Pre order traversal");
    puts("5 In order traversal");
    puts("6 Post order traversal");
    puts("7 Max depth");
    puts("8 Min depth");
    puts("9 Max value");
    puts("10 Min value");
    puts("11 Node Count\n");
    puts("---------------------------------");
    printf("Select an option:");
}

int my_scanf()
{
    char buf[50]={0};

    int option=0;

    fgets(buf,sizeof (buf),stdin);
    sscanf(buf,"%i",&option);

    return option;
}

void new_node(PNODE* n,int value)    //创建节点
{
    *n=(PNODE)malloc(sizeof (NODE));//开辟一个节点

    if (*n!=NULL)
    {
        (*n)->value=value;   //赋值
        (*n)->left=NULL;     //初始化
        (*n)->right=NULL;   
    }
}

void free_node(PNODE* n)      //释放节点
{
    if ((*n)!=NULL)
        free(*n);

    *n=NULL;
}
  
void free_tree(PNODE* n)      //释放二叉树
{
    if (*n==NULL)  
        return ;

    if ((*n)->left!=NULL)  
        free_tree(&(*n)->left);   //进行递归释放左节点

    if ((*n)->right!=NULL)
        free_tree(&(*n)->right);  //进行递归释放右节点

    free_node(n);                 //释放节点

    *n=NULL;
}

PNODE find_node(PNODE n,int value) //查找节点
{
    if (n==NULL)                          //如果节点为空则返回
        return NULL;

    if (n->value==value)                  //如果找到数据,则返回该数据的指针
        return n;
  
    if (value<=n->value)                  
         return find_node(n->left,value);

    return find_node(n->right,value); 

}

void insert_node(PNODE* n,int value) //插入节点
{
    if (*n==NULL)   //找到插入的位置
        new_node(n,value);       
    else if (value==(*n)->value)
        return ;
    else if (value<(*n)->value)
        insert_node(&((*n)->left),value);
    else
        insert_node(&((*n)->right),value);

}

int get_max_depth(PNODE n)   //最长位置
{
    int left=0;
    int right=0;

    if (n==NULL)
        return 0;

    if (n->left!=NULL)
        left=get_max_depth(n->left)+1;

    if (n->right!=NULL)
        right=get_max_depth(n->right)+1;

    return (left>right?left:right);
}

int get_min_depth(PNODE n)           //最短位置
{
    int left=0;
    int right=0;

    if (n==NULL)
        return 0;

    if (n->left!=NULL)
        left=get_min_depth(n->left)+1;

    if (n->right!=NULL)
        right=get_min_depth(n->right)+1;

    return (left<right?left:right);
}

int get_num_nodes(PNODE n)           //获取节点数目
{
    int left=0;
    int right=0;

    if (n==NULL)
        return 0;

    if (n->left!=NULL)
        left=get_num_nodes(n->left);

    if (n->right!=NULL)
        right=get_num_nodes(n->right);

    return (left+1+right);
}

int get_min_value(PNODE n)           //最短路径长度
{
    if (n==NULL)
        return 0;

    if (n->left==NULL)
        return n->value;

    return get_min_value(n->left);
}

int get_max_value(PNODE n)           //最大路径长度
{
    if (n==NULL)
        return 0;

    if (n->right==NULL)
        return n->value;

    return get_max_value(n->right);
}

void deletenode(PNODE *n)    //删除节点
{
    PNODE tmp=NULL;

    if ((*n)==NULL)
        return ;

    if ((*n)->right==NULL)
    {
        tmp=*n;
        *n=(*n)->left;

        free_node(n);
    }
    else if ((*n)->left==NULL)
    {
        tmp=*n;
        *n=(*n)->right;

        free_node(n);
    }
    else 
    {
        for (tmp=(*n)->right;tmp->left!=NULL;tmp=tmp->left);

        tmp->left=(*n)->left;

        tmp=(*n);

        *n=(*n)->right;

        free_node(&tmp);
    }
}

void delete_node(PNODE* n,int value)
{
    PNODE node=NULL;

    if ((*n)==NULL)
        return ;

    node=find_node(*n,value);

    if ((*n)->value==value)
        deletenode(n);
    else if (value<(*n)->value)
        delete_node(&((*n)->left),value);
    else 
        delete_node(&((*n)->right),value);
}

void pre_order_traversal(PNODE n)      //前序遍历
{
    if (n!=NULL)
    {
        printf("%i ",n->value);

        pre_order_traversal(n->left);
        pre_order_traversal(n->right);
    }
}

void in_order_traversal(PNODE n)       //中序遍历
{
    if (n!=NULL)
    {
        in_order_traversal(n->left);

        printf("%i ",n->value);

        in_order_traversal(n->right);
        
    }
}

void post_order_traversal(PNODE n)     //后序遍历
{
    if (n!=NULL)
    {
        post_order_traversal(n->left);
        post_order_traversal(n->right);

        printf("%i ",n->value);
    }
}

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-05-10 13:07
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 14楼 九转星河
嗯,好的。给我点时间。无论如何,无论有没有找到问题出在哪里,我都告诉你一声。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-10 13:10
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 14楼 九转星河
我测试了一下,我没有发现有BUG啊,删除值之后一切正常。
我进行了大概50次测试,没有问题哦。

或者你告诉我一下输入序列,我试试。

嗯……终于发现了。

程序代码:
/*545 407 58 10 86 374 90 96 312 423 458 905 732 661 572 648 757 784 936 942
删除的值为545
905 732 661 572 407 58 10 86 374 90 96 312 423 458 648 757 784 936 942
删除的值为905
936 732 661 572 407 58 10 86 374 90 96 312 423 458 648 757 784 942
删除的值为407
936 732 661 572 423 58 10 86 374 90 96 312 458 648 757 784 942
删除的值为58
936 732 661 572 423 86 10 374 90 96 312 458 648 757 784 942
删除的值为86
936 732 661 572 423 374 90 10 96 312 458 648 757 784 942
删除的值为374
936 732 661 572 423 458 648 757 784 942
删除的值为732
936 757 661 572 423 458 648 784 942
删除的值为757
936 784 661 572 423 458 648 942
删除的值为784
936 942
删除的值为423
936 942
删除的值为661
936 942
删除的值为90
936 942
删除的值为10
936 942
删除的值为96
936 942
删除的值为572
936 942
删除的值为458
936 942
删除的值为936

删除的值为312

删除的值为648

删除的值为942
*/




[此贴子已经被作者于2017-5-10 13:30编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-10 13:25
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
@九转星河

目前所找的问题是,当删除带有两个子树的节点的时候,你意图重建链接。
着一个测试我研究了好久,当删除这样的节点的时候,左子树的位置发生了变化。

顺带,中午的时候,我的DeleteNode函数被我改出了BUG,希望你看的不是有BUG的版本。

程序代码:
389 19 343 181 312 252 304 387 497 490 413 825 807 632 617 759 662 804 843 966
删除的值为389//删除389之后,19的位置后移了,并且413丢失了。
            //为什么会这样,我还没弄清楚。所以……你最好来解释一下你的代码的思路。
            //那段代码发在下面。
497 490 413 19 343 181 312 252 304 387  825 807 632 617 759 662 804 843 966
删除的值为19//这里挺好理解的,当删除19之后,整个19作为根节点的树,都不见了。
497 490 413 825 807 632 617 759 662 804 843 966
删除的值为497
825 807 632 617 490 413 759 662 804 843 966
删除的值为825
843 807 632 617 490 413 759 662 804 966
删除的值为807
843 966



程序代码:
    else 
    {
        for( tmp = ( *n )->right; tmp->left != NULL; tmp = tmp->left )
        ;

        tmp->left = ( *n )->left;

        tmp =( *n );

        *n = ( *n )->right;

        free_node( &tmp );
    }


[此贴子已经被作者于2017-5-10 18:51编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-10 18:46
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 17楼 renkejun1942
我也是对着注释敲的~却没看出与源代码有啥不同~那代码出自一个手机版的数据结构学习宝典~打算自己重做一个重新整理思路~其实不是删除带有两个子节点才有这个问题哦~输入1 2 3 4 5 6 7删除其中一个的时候后面的全部都不见了~现在感觉自己水平还可以~有时间重新做一个~对哦~最近还要做数学建模图论PPT~下周就要拿去演讲30分钟了~虽然资料都要自己手工上网收集~但上网搜到一份感觉很好就打算全抄了~~~~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-05-10 18:55
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
得分:0 
回复 18楼 九转星河
原来如此,那我不纠结了,我以为是你自己写的,那么你肯定知道自己为什么这样写。

我不学别人的代码,我只学别人的思路。也因为这一点,给我带来很多麻烦,因为思路总是基于正确的代码。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-05-10 18:58
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
可以简单地加个释放树函数~完善一下~回收一下空间~感觉链表里面可以带个指针函数~可以通过修改链表指针或者修改指针函数的指向来改变程序的执行步骤~~感觉这样很好玩的~有时间可以去试一下~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-05-10 19:55



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-476865-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.265052 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved