How can I get a non-empty binary tree and print it? - c

I built three files, which includes MainFunc.c, AllFun.h, and OtheFunc.c.
The program happens runtime error, which print nothing. However, I need it output a tree as previous order.
I guess the problem may be that I built an empty tree, but I can't solve it.
MainFunc.c
#include "AllFun.h"
int main(int argc, char* argv[])
{
int nums[MaxSize] = { 0 };
printf("Enter value of root node: ");
for (int i = 0; i < MaxSize; ++i) {
scanf_s("%d", &nums[i]);
}
TreeNode* root = create(nums, MaxSize);
preorder(root);
return 0;
}
AllFun.h
#include <stddef.h> // NULL
#include <stdlib.h>
#include <stdio.h>
#define MaxSize 10
typedef struct node {
int data;
struct node* lchild, * rchild;
} TreeNode;
TreeNode *create(int nums[], int n);
void preorder(TreeNode *root);
OtheFunc.c
#include "AllFun.h"
TreeNode* newNode(int v) {
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
if (node) {
node->data = v;
node->lchild = node->rchild = NULL;
return node;
}
}
void insert(TreeNode* root, int x)
{
if (root == NULL) {
root = newNode(x);
return;
}
if (root->data < x) {
insert(root->lchild, x);
}
else {
insert(root->rchild, x);
}
}
TreeNode *create(int nums[], int n)
{
TreeNode* root = NULL; // Build a empty root node
for (int i = 0; i < n; i++) {
insert(root, nums[i]);
}
return root;
}
void preorder(TreeNode* root)
{
if (root == NULL) {
return;
}
printf("%d ", root->data);
preorder(root->lchild);
preorder(root->rchild);
}

You have to pass the node as a pointer to pointer, then the function can change the pointer:
void insert(TreeNode** root, int x)
{
if (*root == NULL) {
*root = newNode(x);
return;
}
if ((*root)->data < x) {
insert(&(*root)->lchild, x);
}
else {
insert(&(*root)->rchild, x);
}
}
Call with insert(&root, nums[i]);:
https://ideone.com/nV5q1g

Related

How to solve exception thrown in traversing forest

Question: Compute numbers of leaves in forest. Promblem: After debugging and printing a part of data, when I traverse printf("%d ", node->data);, incurred in a runtime error, that is, exception thrown: read access violation.
MainFunc.c
#include "AllFun.h"
int main(int argc, char* argv[])
{
CsNode* tree = (CsNode*)malloc(sizeof(CsNode));
if (tree) {
tree->firstchild = NULL;
tree->nextsibling = NULL;
CreateTree(&tree);
preOrder(tree);
int leaves = CountForestLeaves(tree);
printf("leaves: %d", leaves);
}
return 0;
}
AllFun.h
#include <stdio.h>
#include <stdlib.h>
typedef struct CsNode {
struct CsNode* firstchild;
struct CsNode* nextsibling;
int data;
}CsNode;
void CreateTree(CsNode** node);
void preOrder(CsNode* node);
int CountForestLeaves(CsNode* tree);
OtheFunc.c
#include "AllFun.h"
void CreateTree(CsNode** node)
{
int data;
printf("please input data: ");
scanf_s("%d", &data);
if (data != -1) {
*node = (CsNode*)malloc(sizeof(CsNode));
(*node)->data = data;
(*node)->firstchild = NULL;
(*node)->nextsibling = NULL;
CreateTree(&(*node)->firstchild);
CreateTree(&(*node)->nextsibling);
}
}
void preOrder(CsNode* node)
{
if (node != NULL) {
printf("%d ", node->data);
preOrder(node->firstchild);
preOrder(node->nextsibling);
}
}
int CountForestLeaves(CsNode* tree)
{
if (tree == NULL)
return 0;
if (tree->firstchild == NULL)
return 1 + CountForestLeaves(tree->nextsibling);
else {
return CountForestLeaves(tree->firstchild) + CountForestLeaves(tree->nextsibling);
}
}

Pointer set to NULL but not in debugger

So I am working o AVL tree, however I cant seem to either get the delete function working nor freeing the tree right. The delete function segfaults everytime, but the free function segfaults when in the debugger.
Here is gdb's stack trace:
#0 0x00007fffd935a87a in msvcrt!_memicmp_l () from C:\WINDOWS\System32\msvcrt.dll
#1 0x0000000000402811 in isPresentRecurs (root=0xb756d0, searchedValue=0xb795b0 "aaa", found=0x61fcec) at ../.source/binTree.c:206
#2 0x00000000004027d6 in isPresent (root=0xb756d0, searchKey=0xb795b0 "aaa") at ../.source/binTree.c:200
#3 0x0000000000401c3d in main () at test.c:110
In my tests I check if the root has been set to NULL, which running it normally does finish however running it inside the debugger does not and instead goes into the else statement:
Minimal Example (test.c):
#include "binTree.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRACE 0
#define MAX_SEARCH_ITEMS 20
void fillTree(binTree **tree);
void fillSearchValues( char **valArray);
void fillTree(binTree** tree){
printf( "Constructing tree\n\n" );
char key[200] ="";
for(int j=1 ;j<4;j++ ){
memset(&key,0,199);
for(int i=0; i<26; i++){
for(int k = 0;k<j;k++) key[k]= i+'a';
Var value;
value.data = malloc(sizeof(varData));
value.data->iData = j;
value.type =INTEGER;
(*tree)->root= insert((*tree)->root,key,value);
if(TRACE) printf("key: %s, value: %d\n",(*tree)->root->key,(*tree)->root->value.data->iData);
}
}
(*tree)->nodeCount = getSizeBinaryTree((*tree)->root);
printf( "\n\nTree constructed\n\n" );
}
void fillSearchValues( char **valArray){
char key[200]="";
for(int j=1 ;j<4;j++ ){
memset(&key,0,199);
for(int i=0; i<26; i++){
if(i*j>MAX_SEARCH_ITEMS) break;
for(int k = 0;k<j;k++) key[k]= i+'a';
*(valArray+i*j) = strdup(key);
if (TRACE)printf ("%s read; %s inserted\n", key, valArray[i*j] );
}
}
}
int main(){
binTree *tree = createNewTree();
fillTree(&tree);
printTree(tree->root);
/* //Fails at delete
for(int i=0;i<26;i++){
char string = i+'a';
tree->root = Delete(tree->root,&string);
}*/
printf("\nFreeing Tree: \n=================================\n");
freeTree(tree->root);
if(tree->root==NULL) printf("Tree has been freed successfully\n");
else printf("Failed to free tree \n");
// searching after freeing
int found =0; int lost =0;
char *values[MAX_SEARCH_ITEMS];
fillSearchValues(values);
for(int i=0;i<MAX_SEARCH_ITEMS;i++){
if(isPresent(tree->root,values[i])){
if (TRACE)printf("found search value %s\n",values[i]);
found++;
}else{
lost++;
if(TRACE)printf("didnot find search value %s\n",values[i]);
}
}
printf("found %d of %d while cleared %d\n", found,MAX_SEARCH_ITEMS,lost);
free(tree);
return 0;
}
binTree.h:
#ifndef BINTREE_H
#define BINTREE_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define COUNT 10
typedef enum TYPE {INTEGER, FLOAT, CHARACTER} TYPE;
typedef union {
float fData;
int iData;
char cData;
} varData;
typedef struct Var{
varData * data;
TYPE type;
} Var;
typedef struct Node{
char* key;
Var value;
int height;
struct Node *left;
struct Node *right;
}Node;
typedef struct binTree{
Node *root;
unsigned int nodeCount;
}binTree;
int max(int a,int b);
binTree *createNewTree();
Node *newNode(char *key,Var value);
void freeTree(Node *node);
void freeNode(Node *node);
Node *insert(Node *node,char *key,Var value);
Node *rightRotate(Node *n);
Node *leftRotate(Node *n);
int height(Node *node);
int getBalance(Node *N);
void printTree(Node *root);
void printTreeS(Node *root,int space);
int isPresent(Node *root,char *searchKey);
void isPresentRecurs(Node *root,char *searchedValue,int *found);
Node *minValueNode(Node *node);
Node *search(Node *node,char *key);
Node *Delete(Node *root,char *key);
int getSizeBinaryTree(Node* root);
#endif
binTree.c
#include "binTree.h"
int max(int a, int b){
return (a > b)? a : b;
}
binTree* createNewTree(){
binTree *t = (binTree *) malloc(sizeof(binTree));
if(!t){
printf("Failed at allocationg tree\n");
exit(-1);
}
t->root = NULL;
return t;
}
Node* newNode(char * key,Var value){
Node *p = (Node*)malloc(sizeof(Node));
if(!p){
printf("Failed at allocationg node\n");
exit(-1);
}
p->key = strdup(key);
p->value = value;
p->left=p->right=NULL;
p->height = 1;
return p;
}
void freeTree(Node* node){
if (node==NULL) return;
freeTree(node->left);
freeTree(node->right);
freeNode(node);
node=NULL;
}
void freeNode(Node *node){
free(node->value.data);
node->value.data = NULL;
free(node->key);
node->key = NULL;
free(node);
node = NULL;
}
Node* insert(Node *node, char *key,Var value){
if (node == NULL) return newNode(key,value);
if ( strcasecmp(key ,node->key)<0) node->left = insert(node->left, key,value);
else if (strcasecmp(key ,node->key)>0) node->right = insert(node->right, key,value);
else if(strcasecmp(key,node->key)==0){
if(memcmp(&value.data,&node->value,sizeof(Var))!=0){
memcpy(&node->value,&value,sizeof(Var));
}
return node;
};
node->height = max(height(node->left),height(node->right))+1;
int balance = getBalance(node);
// Left Left Case
if (balance > 1 && strcasecmp(key, node->left->key)<0)
return rightRotate(node);
// Right Right Case
if (balance < -1 && strcasecmp(key, node->right->key)>0)
return leftRotate(node);
// Left Right Case
if (balance > 1 && strcasecmp(key, node->left->key)>0){
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && strcasecmp(key,node->right->key)<0){
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
Node *rightRotate(Node *n){
Node *leftNode =n->left;
if(!leftNode) return n;
Node *rightOfLeft =leftNode->right;
leftNode->right = n;
n->left = rightOfLeft;
n->height = max(height(n->left), height(n->right)) + 1;
leftNode->height = max(height(leftNode->left), height(leftNode->right)) + 1;
return leftNode;
}
Node *leftRotate(Node *n){
Node *rightNode = n->right;
if(!rightNode) return n;
Node *leftOfright = rightNode->left;
rightNode->left = n;
n->right = leftOfright;
n->height = max(height(n->left), height(n->right)) + 1;
rightNode->height = max(height(rightNode->left), height(rightNode->right)) + 1;
return rightNode;
}
int height(Node *node){
if (!node) return 0;
return node->height;
}
int getBalance(Node *N){
if (N == NULL) return 0;
return height(N->left) - height(N->right);
}
void printTree(Node *root){
printTreeS(root, 0);
}
void printTreeS( Node *root, int space){
if (root == NULL)
return;
space += COUNT;
printTreeS(root->right, space);
printf("\n");
for (int i = COUNT; i < space; i++) printf(" ");
if (root->value.type == CHARACTER)printf("type: CHAR key: %s value: %s\n", root->key, root->value.data->cData);
if (root->value.type == INTEGER)printf("type: INT key: %s value: %d\n", root->key, root->value.data->iData);
if (root->value.type == FLOAT)printf("type: FLOAT key: %s value: %f\n", root->key, root->value.data->fData);
printTreeS(root->left, space);
}
int isPresent(Node* root, char* searchKey){
int found = 0;
isPresentRecurs( root, searchKey, &found );
return found;
}
void isPresentRecurs( Node *root,char *searchedValue,int* found ){
if (root) {
if (strcasecmp(root->key,searchedValue)==0)
*found = 1;
else {
isPresentRecurs(root->left, searchedValue, found);
if (!(*found))
isPresentRecurs( root->right, searchedValue, found);
}
}
}
Node * minValueNode(Node* node){
if(!node) return NULL;
if(node->left )return minValueNode(node->left);
return node;
}
Node *search(Node *node, char *key){
if (node == NULL || strcmp(node->key, key)==0)return node;
if (strcmp(node->key, key)<0) return search(node->right, key);
return search(node->left, key);
}
int getSizeBinaryTree(Node* root){
if (root) return 1 +getSizeBinaryTree( root->left ) + getSizeBinaryTree( root->right );
else return 0;
}
Node* Delete(Node* root,char *key) {
if (root==NULL) return root;
else if (strcasecmp(key ,root->key)>0) root->left =Delete(root->left,key);
else if (strcasecmp(key ,root->key)<0) root->right = Delete(root->right,key);
else {
if(root->right==NULL && root->left==NULL) {
free(root);
root = NULL;
}
else if(root->left!=NULL && root->right==NULL) {
Node* temp = root->left;
root = root->left;
freeNode(temp);
}
else if(root->right!=NULL && root->left==NULL) {
Node* temp = root->right;
root = root->right;
freeNode(temp);
}
else {
Node* temp = minValueNode(root->right);
root->key= temp->key;
root->value = temp->value;
root->right = Delete(root->right,temp->key);
}
}
if(root==NULL) return root;
root->height = 1 + max(height(root->left),height(root->right));
int balance = getBalance(root);
//Left Left Case
if(balance > 1 && getBalance(root->left) >=0) return rightRotate(root);
// Right Right Case
if(balance < -1 && getBalance(root->right) <=0) return leftRotate(root);
// Left Right Case
if(balance > 1 && getBalance(root->left) < 0) {
root->left = leftRotate(root->left);
return rightRotate(root);
}
//Right Left Case
if(balance < -1 && getBalance(root->right) > 0) {
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}
This is a mistake:
freeTree(tree->root);
if(tree->root==NULL) printf("Tree has been freed successfully\n");
else printf("Failed to free tree \n");
C uses pass-by-value, so it is not possible for freeTree to set tree->root to NULL.
The line node = NULL; inside the freeTree function sets the function parameter (which is a copy of the argument), it does not modify the argument in the calling context.
The function does free the pointed-to memory, which renders all pointers to that memory indeterminate, so the test tree->root == NULL actually causes undefined behaviour by using an indeterminate value.
Your compiler should warn about a dead-store for node=NULL; , if you do not see a warning then try turning up the warning and/or optimization level in your compiler, or running a static analyzer such as clang-tidy. freeNode has a similar issue.
To fix the problem, either change the calling code, e.g. freeTree(tree->root); tree->root = NULL;, or you will have to use pass-by-pointer, i.e. pass the address of the node you want to free.

cs50 pset5 unload problem - memory leakage

I am trying to solve the cs50 pset5. I am using a tries method.
I can insert word into the tries successfully. However, when i unload the memory, it fails. I am so stuck at the unload problem for a few days.
When I try the unload function, it stated that Erorr Message: double free or corruption (!prev): 0x000000000205d010 ***
It is probably due to my unload function, but i have drawn out the logic. It seems fine to me. Anyone has any idea where to amend?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#define LENGTH 45
#define SIZE_OF_CHILD 27
typedef struct Node {
bool is_word;
struct Node* child[SIZE_OF_CHILD];
} Node;
Node* root;
Node* temp;
Node* create_node(Node* node);
void test();
int cal_key(char c);
Node* insert(const char* word);
void unload(Node* node);
int main() {
root = malloc(sizeof(Node));
if (root == NULL) {
exit(0);
}
root = create_node(root);
temp = malloc(sizeof(Node));
if (temp == NULL) {
exit(0);
}
test();
}
// **************** function to create a node *******************
Node* create_node(Node* node) {
node->is_word = false;
for (int i = 0; i < SIZE_OF_CHILD; i++) {
node->child[i] = NULL;
}
return node;
}
//************* calculate the key value ************
// Assume that the input is in lower case
int cal_key(char c) {
if (isalpha(c)) {
if (islower(c)) {
return c - 'a';
}
else {
return c + 32 -'a';
}
}
else {
return SIZE_OF_CHILD - 1;
}
}
//*************** function to insert an item in the the node ***********
Node* insert(const char* word) {
int str_len = strlen(word);
temp = root;
int key;
for (int i = 0; i < str_len; i++) {
key = cal_key(word[i]);
if (temp->child[key] == NULL) {
Node* node = malloc(sizeof(Node));
if (node == NULL) {
fprintf(stderr, "Error in creating node\n");
exit(0);
}
node = create_node(node);
temp->child[key] = node;
}
temp = temp->child[key];
}
temp->is_word = true;
return root;
}
//***************** function to unload a function ********************
void unload(Node* node) {
// This is to find the last node
for (int i = 0; i < SIZE_OF_CHILD; i++) {
if (node->child[i] != NULL) {
unload(node->child[i]);
}
free(node);
}
}
void test() {
root = insert("Peter");
unload(root);
}

create an array with the values of the nodes at a level

I have to create an array that contains the values of nodes in a level passed as parameter. The function createArray has to return an array containing the values of the nodes at the level passed as parameter. My code is:
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
struct node {
int data;
struct node* left;
struct node* right;
};
struct node* newNode(int data) {
struct node* node = (struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
int numNodesLevel(struct node* root, int level) {
if (root == NULL) {
return 0;
}
else {
if (level == 0) {
return 1;
}
return numNodesLevel(root->left, level - 1) + numNodesLevel(root->right, level - 1);
}
}
int max(int a, int b) {
if(a > b) {
return a;
}
else {
return b;
}
}
int height(struct node* root) {
if (root == NULL) {
return -1;
}
else {
if (root->left == NULL && root->right == NULL) {
return 0;
}
return max(height(root->left), height(root->right)) + 1;
}
}
int maxNodesLevel(struct node* root) {
if (root == NULL) {
return 0;
}
else {
int max = 0;
int h = height(root);
int i = 0;
for (i = 0; i <= h; i++) {
if (numNodesLevel(root, i) > max) {
max = numNodesLevel(root, i);
}
}
return max;
}
}
void fill(struct node* root, int* A, int level, int* i) {
if (root != NULL) {
if (level == 0) {
A[*i] = root->data;
*i = *i + 1;
}
fill(root->left, A, level - 1, i);
fill(root->right, A, level - 1, i);
}
}
int* createArray(struct node* root, int level) {
if (root != NULL) {
int *A = (int*)calloc(maxNodesLevel(root), sizeof(int));
int i = 0;
fill(root, A, level, &i);
return A;
}
}
int main(){
struct node* root = newNode(12);
root->left = newNode(3);
root->right = newNode(16);
root->left->left = newNode(2);
root->left->right = newNode(2);
root->right->left = newNode(2);
root->right->right = newNode(22);
printf("%d", createArray(root,1));
getchar();
return 0;
}
The result should be 3,16 which are the values of the nodes at level 1, but it gives me different numbers like 22721648. These numbers are different every time I run the code, so I think there must be something wrong in the way I use pointers, but I can't figure out where is the error.
Can somebody help me?
The code is correct, but only mistake here is createArray() returns an array and you are considering it as int.
Add following code instead of printf() and it will work.
int level = 1, *arr;
arr = createArray(root, level);
for(int i = 0; i < 2 * level; i++){
printf("%d ", arr[i]);
}
Hope it will help !!

I can't inset a node to bin search tree

I want to write a BST,but the insert function doesn't work. Debugging it , I found that it was not inserting.
/* Binary Search Tree (BST).demo */
#include <stdio.h>
#include <stdlib.h>
typedef struct treeNode{
int data;
struct treeNode* lChild;
struct treeNode* rChild;
} treeNode;
treeNode* createNode(){
treeNode *nNode;
nNode=(struct treeNode*)malloc(sizeof(treeNode));
nNode->data=0;
nNode->lChild=NULL;
nNode->rChild=NULL;
return nNode;
}
void insert(treeNode* rt,int idata)
{
if(rt==NULL){
treeNode* nNode;
nNode=createNode();
nNode->data=idata;
rt=nNode;
rt->lChild=NULL;
rt->rChild=NULL;
}else{
if(idata < rt->data)
insert(rt->lChild,idata);
else insert(rt->rChild,idata);
}
}
int main()
{
treeNode *root;
root=(treeNode*)malloc(sizeof(treeNode));
root->data=15;
root->lChild=NULL;
root->rChild=NULL;
insert(root,13);
if(root->lChild==NULL)
printf("root no l child\n");
// printf("root lchild data :%d",root->lChild->data);
return 0;
}
use this as the insert function :
void insert(treeNode** rt,int idata)
{
if((*rt)==NULL)
{
treeNode* nNode;
nNode=createNode();
nNode->data=idata;
*rt=nNode;
(*rt)->lChild=NULL;
(*rt)->rChild=NULL;
}
else
{
if(idata < (*rt)->data)
insert(&((*rt)->lChild),idata);
else
insert(&((*rt)->rChild),idata);
}
}
and the insert function call in main() as:
insert(&root,13);
I usually implement it like this:
void insert(treeNode* rt, int idata) {
// assert( rt != NULL );
if(idata < rt->data){
if( rt->lChild != NULL)
insert(rt->lChild, idata);
else {
rt->lChild = createNode();
rt->lChild->data = idata;
}
} else {
if( rt->rChild != NULL)
insert(rt->rChild, idata);
else {
rt->rChild = createNode();
rt->rChild->data = idata;
}
}
}
Moreover, I prefer give an argument to createNode()
treeNode* createNode(int idata){
// ...
nNode->data = idata;
// ...
}
So the insert will look like:
void insert(treeNode* rt, int idata) {
// ...
rt->lChild = createNode(idata);
// ...
rt->rChild = createNode(idata);
// ...
}

Resources