【问题标题】:linear algorithm on a binary three in-order-visit-like二进制三有序访问的线性算法
【发布时间】:2015-09-14 01:35:09
【问题描述】:

我必须用 C 语言编写一个算法,该算法接受二叉搜索树的输入。该练习将访问定义为“左访问”,即从子树的根开始并尽可能向左走。同样,它定义了“正确的访问”。练习要求打印左访问严格大于右访问的三个键。它还要求按升序打印此密钥,并且该算法必须在线性时间内工作,因此我必须实现一个类似按顺序访问的算法。现在,我编写了一个在线性时间内工作的算法,但在某些情况下它不能作为按顺序访问,因此打印的密钥不是按升序排列的,但我不知道如何管理克服这个障碍。如何在不首先实现左右递归的情况下比较左访问和右访问?

#include<stdio.h>
#include<stdlib.h>


typedef struct _node {
        int dato;
    struct _node *left;
        struct _node *right;
}node;


typedef struct _ret {
        int sin;
        int des;
        }res;


node *inserisci(node *root, int insert)
{
 if(root==NULL) {
        node * new=(node*)malloc(sizeof(node));
        new->left=NULL;
        new->right=NULL;
        new->dato=insert;
        return new;
}
 if(root->dato < insert) root->right =inserisci(root->right,insert);
 else root->left = inserisci(root->left,insert);
 return root;
}


res somma(node * u)
{
res ret; res ciao_sx; res ciao_dx;

if(u==NULL) return;

if(u->left==NULL && u->right==NULL)
        {
        ret.sin=0;
        ret.des=0;
        return ret;
        }

if(u->left!=NULL && u->right!=NULL)
        {
        ciao_sx=somma(u->left);
        ret.sin= ciao_sx.sin+1;
        ciao_dx=somma(u->right);
        ret.des= ciao_dx.des+1;

        if(ret.sin > ret.des )
                {
                printf("%d\n",u->dato);
                }
        return ret;
        }

if(u->left!=NULL && u->right==NULL)
        {
        ciao_sx=somma(u->left);
        ret.sin= ciao_sx.sin+1;
        ret.des= 0;
        printf("%d\n",u->dato);

        return ret;
        }

if(u->left==NULL && u->right !=NULL)
        {
        ciao_dx=somma(u->right);
        ret.des= ciao_dx.des +1;
        ret.sin=0;
        return ret;

        }
}





int main()
{
int n,i,x;
scanf("%d",&n);
node *root=NULL;
for(i=0;i<n;i++) {
        scanf("%d",&x);
        root=inserisci(root,x);
}

somma(root);

return 0;
}

【问题讨论】:

  • 把代码也贴出来
  • 或许还能学会使用调试器
  • 我不知道如何发布代码并且我编写的代码有效,没有错误。你能解释一下如何发布代码吗?谢谢!
  • 复制粘贴并使用代码格式选项
  • @GiovanniMauro 只需复制并粘贴代码,然后使用鼠标选择代码并按 ctrl-k。

标签: c algorithm binary-search-tree


【解决方案1】:

这个问题可以在线性时间内解决。

诀窍是以 BOTTOM-UP 方式计算左访问和右访问值,以便我们可以执行以下操作

left_visit of node = left_visit of its left child + 1

right_visit of node = right_visit of its right child + 1

条件:

if(node is null)
 left_vist is 0 as well as right_visit is also 0.

因为我们可以很容易地使用中序遍历以自下而上的方式追踪这条路径,我们将使用它计算 left_visit 和 right_visit 的值。

主要思想

我们知道我们可以很容易地编写递归中序遍历。

而且我们知道,当我们遇到一个没有左孩子的节点时,我们已经到达底部,所以这是我们开始使用上面指定的规则计算值的地方。

这会起作用的原因是,当对一个节点的左子节点的中序遍历的递归调用完成时,它的左子节点将计算其 left_visit 并且 我们所要做的就是加 1 来计算当前节点的 left_visit 值和相同的逻辑适用于 right vit。

时间复杂度是O(N),即线性的,因为中序遍历是在线性时间内完成的。

使用上面的算法,下面是C代码:

#include <stdio.h>
#include <stdlib.h>
typedef struct tree tree;
struct tree{
   int value;
   tree *left;
   tree *right;       
   int lv;
   int rv;
};
tree *insert(tree *ptr,int x)
{
    if(ptr==NULL)
    {
        ptr=(tree *)malloc(sizeof(tree));
        ptr->left=NULL;
        ptr->right=NULL;
        ptr->value=x;            
        return ptr;
    }
    else if(ptr->value>x)
        {ptr->left=insert(ptr->left,x);return ptr;}
    else { ptr->right=insert(ptr->right,x);return ptr;}
}
void compute_values(tree *ptr)
{
    if(ptr==NULL)
    return;
    compute_values(ptr->left);
    if(ptr->left==NULL)
     ptr->lv=0;
    else ptr->lv=ptr->left->lv+1;    
    compute_values(ptr->right);
    if(ptr->right==NULL)
     ptr->rv=0;
    else ptr->rv=ptr->right->rv+1;   
}
void iot(tree *ptr)
{
    if(ptr==NULL)
     return;
    iot(ptr->left);  
      if(ptr->lv > ptr->rv)
       printf("%d ",ptr->value);
    iot(ptr->right);
}
int main()
{
    tree *root=NULL;
    int i;
    /*insert 6  elements*/        
     root=insert(root,4);
     root=insert(root,5);
     root=insert(root,3);
     root=insert(root,1);
     root=insert(root,2);
     root=insert(root,0);
     root=insert(root,6);
     compute_values(root);/*compute the left and right visit.*/
     printf("the nodes which have left visit strictly > than right visit\n");
     iot(root);/*inorder traversal*/   
}

【讨论】:

  • 只是一点点。没有参数,int main() 是正确的int main (void)。是的,我知道你知道,但是在向其他人提供可能没有的答案时,最好在语法上尽可能正确。 (防止传递坏习惯......)因为它是一个int foo (void),它返回一个值回shell(即使MS让你没有它就逃脱)。 return 0; 最后。
  • 可能还有其他小修复。 ptr = malloc (sizeof *ptr); 将是首选。见:Do I cast the result of malloc?
猜你喜欢
  • 2019-11-15
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
  • 1970-01-01
  • 2017-09-23
  • 1970-01-01
  • 2022-10-06
相关资源
最近更新 更多