I am trying to build a binary tree from an unsorted float array for an assignment, but I cannot quite figure it out. 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(). 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. The function returns nleft
, the number of values on the left of mid
. I then want to recursively call partition_data()
to create new left
and right
child nodes. 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. 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()
:
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:
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 thanxmin
and less thanxmax
Now don't see xdata[]
as array xdata[]
but see xdata
as the pointer to the first element I have to process. 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
. 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). So you should have:
node->right=build_tree(xdata + (ndata-nright),mid,xdata[nleft],xmax);
to create your right node!