简体   繁体   English

难以从数组构造二叉树

[英]Difficulty Constructing Binary Tree from Array

I am trying to build a binary tree from an unsorted float array for an assignment, but I cannot quite figure it out. 我正在尝试从一个未排序的float数组构建一个二叉树,以进行分配,但是我无法完全弄清楚。 My goal is to send the unsorted array xdata of size ndata to the function build_tree() , which creates a new node using the function create_node(). 我的目标是将大小为ndata的未排序数组xdata发送到函数build_tree() ,该函数使用函数create_node()创建一个新节点。 In the case that the array size is greater than 1, it will call the function paritition_data() (which works fine, but I've placed it at the bottom of the question for reference), which will swap the order of array values so that all values less than mid fall on its left, and greater values to its right. 在数组大小大于1的情况下,它将调用函数paritition_data() (效果很好,但是我将其放在问题的底部以供参考),它将交换数组值的顺序,因此所有小于mid值的值均落在其左侧,而较大值则在其右侧。 The function returns nleft , the number of values on the left of mid . 该函数返回nleft ,即mid左边的值的数量。 I then want to recursively call partition_data() to create new left and right child nodes. 那么我想递归调用partition_data()来创建新的leftright子节点。 I think it is at this step that my program seems to fail, and despite it compiling, the program seems to recursively call partition_data() infinitely, and I'm not sure why. 我认为是在此步骤中我的程序似乎失败了,尽管编译了该程序,但该程序似乎递归地无限调用了partition_data() ,我不确定为什么。 I appreciate any help. 感谢您的帮助。

typedef struct treenode_struct {
  int n;
  float data;
  struct treenode_struct *left, *right;
} treenode;

treenode *create_node( ) {
  treenode *node;

  node = malloc(sizeof(treenode));
  if (node == NULL) {
    printf("Allocate Failed");
    exit(-1);
  }
  node->n = 0;
  node->right = NULL;
  node->left = NULL;

  tree_nodes++;

  return node;
}

treenode *build_tree( float xdata[], int ndata, float xmin, float xmax ) {
  treenode *node;
  int nleft;
  float mid = (xmin+xmax)/2.;

  node = create_node();
  node->n = ndata;
  if (ndata == 1) {  // Add code for this case
    node->data = xdata[0]; 
    node->left = NULL;
    node->right = NULL;
    return node;
  }
  if (ndata == 0){
    printf("Allocate failed\n");
    exit(-1);
  }
 // More than one data point: use partition function
  if (ndata > 1) {
    nleft = partition_data(xdata,ndata,mid);
    int nright = ndata-nleft;

    // Add code to make a left child
    if(nleft != 0){
      node->left=build_tree(xdata,nleft,xmin,xdata[nleft-1]);
    }
    else{
      node->left = NULL;
    }

    // Add code to make a right child
    if(nright != 0){
      node->right=build_tree(xdata,nright,xdata[nleft],xmax);
    }
    else{
      node->right = NULL;
    }
    return node;
  }
}

int tree_nodes;

int main() {
  const int ndata = 16;
  float xdata[] = { 0.963,  0.003, 0.0251, 0.353, 0.667, 0.838, 0.335, 0.915,
            0.796, 0.833, 0.345, 0.871, 0.089, 0.888, 0.701, 0.735 };
  int i;
  float xmiddle = 0.5;
  printf("Input data:\n");
  for (i=0;i<ndata;i++) printf("%f ",xdata[i]);
  printf("\n");

 treenode *tree_root;
  float tree_xmin, tree_xmax;
  tree_nodes = 0;

  tree_xmin = 0;
  tree_xmax = 1;
  tree_root = build_tree( xdata, ndata, tree_xmin, tree_xmax );
  printf("Tree Built: nodes %d\n",tree_nodes);

  printf("Tree Ordered data:\n");
  for (i=0;i<ndata;i++) printf("%f ",xdata[i]);
  printf("\n\n");
}

Here is partition_data() : 这是partition_data()

int partition_data( float xdata[], int ndata, float xmiddle ) {

  // Your code goes here
  int left = 0;
  int right = ndata-1;
  float temp;
  while(left < ndata){  //left loop
    if(xdata[left] < xmiddle){
      if(left == right){
    return left+1;
    break;
      }//DONE
      left = left + 1;
    }
    else{
      while(right<ndata){ //right loop, search for swappable Xright
    if(xdata[right] >= xmiddle){//X[right] is greater than/equal to xmiddle
      if(left == right){
        return left;
        break;
      }
      right=right-1;
    }
    else{ //found X[right] to swap
      temp = xdata[left];
      xdata[left] = xdata[right];//swap
      xdata[right]=temp;
      right = right-1;
      if(left == right) {
        return left+1;
        break;
      }
      left=left+1;
      break;
    }
    break;
      }
    }
  }

Your recursion problem is caused by the creation of your right node. 您的递归问题是由右节点的创建引起的。
You create the right node with this code: 使用以下代码创建正确的节点:

// Add code to make a right child
if(nright != 0){
  node->right=build_tree(xdata,nright,xdata[nleft],xmax);
}
else{
  node->right = NULL;
}

Now if you look at your build_tree function what you have is: 现在,如果您查看build_tree函数,您将拥有:

treenode *build_tree( float xdata[], int ndata, float xmin, float xmax )

Let's interprete it as: 让我们将其解释为:

create a tree from the array xdata[] where all elements are greater than xmin and less than xmax 从数组xdata[]创建一棵树,其中所有元素都大于xmin并且小于xmax

Now don't see xdata[] as array xdata[] but see xdata as the pointer to the first element I have to process . 现在,不要将xdata[]视为数组 xdata[]而是将xdata视为指向我必须处理的第一个元素指针 This will (hopefully) help you understand it a little bit (and is actually what it is, it is just a pointer). 这(希望)可以帮助您稍微了解一下(实际上就是它,它只是一个指针)。 In your code to create the right node you use: 在用于创建正确节点的代码中,使用:

 node->right=build_tree(xdata,nright,xdata[nleft],xmax);

but there you actually insert as right node the root of the tree that will be created by processing the data starting at the first element of your array. 但是实际上您在这里插入了树的根作为右节点,该树的根将通过处理从数组的第一个元素开始的数据来创建。 That's not the slice of the array you want. 那不是您想要的数组的一部分。 The slice you want to have in your right node is the right part of the array so the part that starts at index ndata-nright . 您想在右侧节点中拥有的切片是数组的右侧部分,因此该部分从索引ndata-nright So if you want to change the begin of an array, you just add the index to the pointer of the array. 因此,如果要更改数组的开头,只需将索引添加到数组的指针。 So in your case xdata + (ndata-nright) will represent an array that starts at element ndata-nright (or pointer to that element). 因此,在您的情况下, xdata + (ndata-nright)将代表一个从元素ndata-nright (或指向该元素的指针)开始的数组。 So you should have: 因此,您应该具有:

  node->right=build_tree(xdata + (ndata-nright),mid,xdata[nleft],xmax);

to create your right node! 创建您的正确节点!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM