Data read by fread is longer than what I wrote with fwrite - c

I made a program that can look for prime numbers. It works fine until it hits a point where the file is suddenly longer than what I wrote with fwrite. Here is the code. I am sorry, it is a bit long, but it is complete and executable.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
long long *loadPrimeNums(char *fileName);
void putPrimeNumsInList(long long *primeNums);
void addIntNode(void);
void initialize(void);
void DestroyIntNodes(void);
void writeInFile(void);
void run(void);
int main ()
{
initialize();
putPrimeNumsInList(loadPrimeNums("primeNums"));
run();
writeInFile();
DestroyIntNodes();
_fcloseall();
return 0;
}
Second file:
#include <stdio.h>
#include <stdlib.h>
struct longLongNode
{
long long value;
struct longLongNode *next;
};
long long *loadPrimeNums(char *fileName);
void putPrimeNumsInList(long long *primeNums);
void addLongLongNode(void);
void initialize(void);
void DestroyIntNodes(void);
void writeInFile(void);
void run(void);
FILE *primeNums_fp;
long long currentOffset;
struct longLongNode *head, *tail, *lastOldPrimeNum;
void run()
{
struct longLongNode *current;
current = head;
int isPrime = 1;
for (int i = 0; i < 100; i++)
{
while (current != NULL)
{
if (currentOffset % current->value == 0)
{
isPrime = 0;
break;
}
current = current->next;
}
if (isPrime == 0)
{
isPrime = 1;
}
else
{
addLongLongNode();
}
currentOffset++;
current = head;
}
}
void writeInFile()
{
int numberOfNewPrimes = 0;
long long *newPrimes;
struct longLongNode *current;
current = lastOldPrimeNum;
while (current->next != NULL)
{
numberOfNewPrimes++;
current = current->next;
}
if (numberOfNewPrimes > 0)
{
current = lastOldPrimeNum->next;
newPrimes = (long long *)malloc(sizeof *newPrimes * numberOfNewPrimes);
for (int i = 0; i < numberOfNewPrimes; i++)
{
newPrimes[i] = current->value;
current = current->next;
}
fseek(primeNums_fp, 0L, 2);
fwrite(newPrimes, sizeof *newPrimes, numberOfNewPrimes, primeNums_fp);
printf("Freeing newPrimes: The array that is used to write the new prime numbers to file.\n");
free(newPrimes);
}
}
void initialize()
{
head = (struct longLongNode *)malloc(sizeof *head);
head->value = 2;
head->next = NULL;
lastOldPrimeNum = head;
}
void addLongLongNode()
{
struct longLongNode *temp;
temp = (struct longLongNode *)malloc(sizeof *temp);
temp->value = currentOffset;
temp->next = NULL;
tail->next = temp;
tail = temp;
}
long long *loadPrimeNums(char *fileName)
{
int num;
long long *ret;
primeNums_fp = fopen("primeNums", "a+");
fseek(primeNums_fp, 0L, 2);
if (ftell(primeNums_fp) != 0)
{
if (ftell(primeNums_fp) % sizeof *ret == 0)
{
num = ftell(primeNums_fp) / sizeof *ret;
ret = (long long *)malloc(sizeof *ret * (num + 1));
rewind(primeNums_fp);
fread(ret, sizeof *ret, num, primeNums_fp);
ret[num] = -1;
return ret;
}
else if (ftell(primeNums_fp) != -1)
{
printf("ERROR!!! ftell(fp): %d", ftell(primeNums_fp));
_fcloseall();
exit(0);
}
}
return NULL;
}
void putPrimeNumsInList(long long *primeNums)
{
struct longLongNode *current, *temp;
current = head;
tail = head;
if (primeNums != NULL)
{
for (int i = 0; primeNums[i] != -1; i++)
{
temp = (struct longLongNode *)malloc(sizeof *temp);
temp->value = primeNums[i];
temp->next = NULL;
current->next = temp;
current = temp;
}
tail = current;
lastOldPrimeNum = current;
}
currentOffset = current->value + 1;
printf("Freeing primeNums: The array that contains the initially loaded prime numbers of the file.\n");
free(primeNums);
}
void DestroyIntNodes()
{
struct longLongNode *current, *next;
current = head;
for (int i = 1; current != NULL; i++)
{
next = current->next;
printf("%d: Freeing %d\n", i, current->value);
free(current);
current = next;
}
}
What I get after finding 384 prime numbers is an error message that I made myself which shows how big the file is. The file should be divisible by 8, because the prime numbers are stored as long long integers, but at some point I got a file size of 3073.
Edit: You need to run the program multiple times for the error to occur. I did not know how to multithread, so I made it so it stops after a 100 iterations. Then the prime numbers it found will be stored in a file which should be divisible by 8, but isn't.
Edit2: At the start, the file does not exist. And I am using Windows 10. I am trying now the suggestion of setting fopen mode "ab+".
Edit3: Solved thanks to #user3121023!!

Related

How to store array of linked lists in a binary file?

I would like to save an array of linked lists in a binary file, but I don't know how to assign the dynamic memory due to the varying lengths of linked lists for each bucket.
And to access a random position containing the whole linked list without reading the whole file, like a kind of index file?
Some tip?
I will make these assumptions:
Every (non-“null”) element of each list is an int
There are MAX_INT or fewer elements in each list
Make your file (remember to open in binary mode) have the following structure:
Output an int containing the number of items in the first list
Output each int in that list
Repeat for each subsequent list
This scheme has two drawbacks:
each list has a (large) maximum number of elements
you must traverse each list twice to save (first to learn the length, again to save each item)
It has the advantage of being very quick and direct to load.
here is a simple code,you can use fwrite to file and fread from file as you wish,but you must consider the big-endian or little-endian
#include <stdio.h>
#include <stdlib.h>
typedef struct _Node {
struct _Node *next;
int val;
} Node;
void serialize(Node arr[], int size[], int len) {
FILE *f = fopen("serialize.bin", "wb");
//write arr len
fwrite(&len, sizeof(int), 1, f);
//write array
for (int i = 0; i < len; ++i) {
//write linklist len
fwrite(&size[i], sizeof(int), 1, f);
Node *tmp = &arr[i];
while (tmp) {
fwrite(&tmp->val, sizeof(int), 1, f);
tmp = tmp->next;
}
}
fclose(f);
}
Node *deserialize() {
FILE *f = fopen("serialize.bin", "rb");
int len;
fread(&len, sizeof(int), 1, f);
Node *ret = malloc(len * sizeof(Node));
for (int i = 0; i < len; ++i) {
int linklen;
int val;
Node *tmp = &ret[i];
fread(&linklen, sizeof(int), 1, f);
fread(&val, sizeof(int), 1, f);
ret[i].val = val;
ret[i].next = NULL;
linklen--;
while (linklen--) {
fread(&val, sizeof(int), 1, f);
tmp->next = malloc(sizeof(Node));
tmp->next->next = NULL;
tmp->next->val = val;
tmp = tmp->next;
}
}
return ret;
}
int main() {
#define ARRAY_LEN 3
Node arr[ARRAY_LEN];
int size[ARRAY_LEN];
arr[0].next = malloc(sizeof(Node));
arr[0].val = 1;
arr[0].next->next = malloc(sizeof(Node));
arr[0].next->val = 2;
arr[0].next->next->next = NULL;
arr[0].next->next->val = 3;
size[0] = 3;
arr[1].next = malloc(sizeof(Node));
arr[1].val = 11;
arr[1].next->next = NULL;
arr[1].next->val = 22;
size[1] = 2;
arr[2].next = NULL;
arr[2].val = 33;
size[2] = 1;
serialize(arr, size, ARRAY_LEN);
Node *ret = deserialize();
//TODO free memory
return 0; //end of code
}
The solution is not very complicated if there is a value that is never stored as an element in your linked list-- in that case, you can treat the linked list like a glorified null-terminated string, where whatever value that cannot exist in the linked list acts as the terminator. If you don't have such luxury, then you can write an extra byte with each value that determines if the value is the last one or not. Here's an implementation of the first possible solution, though it can be easily modified to work in the case of the second:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NODE_V_SIZE sizeof(int)
const int list_end = -1;
typedef struct Node {
int value;
struct Node *prev, *next;
} Node;
void free_nodes(Node *head) {
while (head) {
Node *to_free = head;
head = head->next;
free(to_free);
}
}
Node* new_node(int value) {
Node *node = malloc(sizeof(Node));
if (!node) {
return NULL;
}
node->prev = NULL;
node->next = NULL;
node->value = value;
return node;
}
int write_nodes(int fd, Node *head) {
while (head) {
if (write(fd, &head->value, NODE_V_SIZE) != NODE_V_SIZE) {
return -1;
}
head = head->next;
}
if (write(fd, &list_end, NODE_V_SIZE) != NODE_V_SIZE) {
return -1;
}
return 0;
}
Node* read_nodes(int fd) {
Node *head = NULL;
Node *cur = NULL;
int in;
while (1) {
if (read(fd, &in, NODE_V_SIZE) != NODE_V_SIZE) {
free_nodes(head);
return NULL;
}
if (in == list_end) {
return head;
}
if (cur) {
cur->next = new_node(in);
if (!cur->next) {
free_nodes(head);
return NULL;
}
cur->next->prev = cur;
cur = cur->next;
} else {
cur = new_node(in);
if (!cur) {
return NULL;
}
head = cur;
}
}
}
Node* new_random_list(int modifier) {
Node *head = new_node(0);
if (!head) {
printf("out of memory\n");
exit(1);
}
Node *cur = head;
for (int i = 0; i < 10; i++) {
cur->next = new_node((i+modifier)*3);
if (!cur->next) {
free_nodes(head);
printf("out of memory\n");
exit(1);
}
cur = cur->next;
}
return head;
}
int main() {
#define NHEADS 10
// open file
int fd = open("dat", O_RDWR);
if (fd == -1) {
printf("failed to open file\n");
exit(1);
}
// make NHEADS number of 10 nodes linked together and write them to fd
for (int i = 0; i < NHEADS; i++) {
Node *head = new_random_list(i);
if (write_nodes(fd, head)) {
printf("failed to serialize nodes\n");
exit(1);
}
free_nodes(head);
}
// read from fd to populate got then print it, repeat NHEADS times
lseek(fd, 0, SEEK_SET);
for (int i = 0; i < NHEADS; i++) {
Node *got = read_nodes(fd);
if (!got) {
printf("failed to deserialize nodes\n");
exit(1);
}
Node *head = got;
while (got) {
printf("%d\n", got->value);
got = got->next;
}
printf("\n");
free_nodes(head);
}
close(fd);
return 0;
}

Stack push function using c, implemented using doubly linked list

I am trying to implement Hierholzer's algorithm using C.
I have made a push function for a simple stack implemented using doubly linked list but the pointer always moves on to the else condition, even when the starting node is empty.
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<stddef.h>
typedef struct node
{
int source;
int num;
struct node *l, *r;
int done;
}node;
void push(int source, int num, struct node *head)
{
node *n = malloc(sizeof(node));
n->num = num;
n->l = NULL;
n->done = 0;
n->source = source;
if (*head == NULL)
{
head = n;
head -> r = NULL;
}
else
{
n -> r = head;
head->l = n;
head = n;
}
}
int pop(node *head)
{
if(head == NULL)
{
return -1;
}
else
{
node *temp = head;
head = head->r;
int num = temp->num;
free(temp);
return num;
}
}
void append(node *extra, node *head)
{
node *temp = extra;
while(temp->r != NULL)
{
temp = temp->r;
}
temp->r = head;
head->l = temp;
head = extra;
}
node** read(int num)
{
char a[2000] = "Assignment1.txt" ,c[1000];
FILE *f = fopen(a,"r");
printf("Got file\n");
node *adj[num];
int i=0;
node *l;
printf("l: %d\n", l);
while(fscanf(f,"%s",c))
{
char *p = strtok(c, ",");
while(p!=NULL)
{
push(i, atoi(p), l);
p = strtok (NULL, ",");
}
adj[i++] = l;
}
printf("Adjacency list created\n");
return adj;
}
node* euler(node *adj[],int n, int i)
{
node *cpath = NULL;
node *fin = NULL;
node *extra;
node *temp = adj[i];
node *tempi;
while(temp!=NULL)
{
if(temp->r->r == NULL)
{
tempi = temp;
}
if(temp->done == 0)
{
temp->done = 1;
push(i, temp->num, cpath);
extra = euler(adj, n, temp->num);
append(extra, cpath);
}
else
{
temp = temp->r;
}
}
while(tempi->l != NULL)
{
push(i,tempi->num, fin);
extra = euler(adj, n, tempi->num);
append(tempi, fin);
tempi = tempi->l;
}
if(tempi != NULL)
{
push(i,tempi->num, fin);
extra = euler(adj, n, tempi->num);
append(tempi, fin);
}
return fin;
}
int main()
{
int n;
printf("Enter the number of vertices: ");
scanf("%d", &n);
node **adj = read(n);
node *fin = euler(adj, n, 0);
node *temp = fin;
while(temp!=NULL)
{
printf("%d ", temp->num);
temp = temp->r;
}
return 0;
}
I am yet to debug the entire code but I am getting stuck at the read() function where the input is an Assignment1.txt which includes:
2,3
3,1
1,2
I am not able to understand why I am getting a segmentation fault.
The function deals with a copy of the value of the passed to it pointer to the head node. So the original pointer itself is not changed in the function. It is the copy of the value of the passed pointer that is changed within the function.
You need to pass the pointer by reference that is indirectly through pointer to the pointer.
The function can be declared and defined the following way.
int push( struct node **head, int source, int num )
{
node *n = malloc(sizeof(node));
int success = n != NULL;
if ( success )
{
n->source = source;
n->num = num;
n->done = 0;
n->l = NULL;
n->r = *head;
if ( *head != NULL ) ( *head )->l = n;
*head = n;
}
return success;
}
In read function you are returning adj. However, it is a local variable. You are not using malloc type function. So, local variables destroy after function returned. Therefore, you are trying to access a random place when you try to access adj in main. I guess the problem is caused by this reason.

Not reading number properly?

I'm trying to read from file line by line. It takes the first number of the line and the rest it connects it using a char of linked list. But when I run it, i get the connection as -38 (which is wrong) and it only prints it once and does not go through the rest of the line. but it reads first element perfectly.
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node* next;
};
int main(void)
{
FILE * fp;
char * line = NULL;
char * storage;
size_t len = 0;
ssize_t read;
struct node *G[1000];
for (int i = 1; i < 1000; i++)
{
G[i]= malloc(sizeof(struct node));
G[i]->data = i;
G[i]->next = NULL;
}
fp = fopen("idk2.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
int vertexGettingConntected = line[0];
struct node* newItem;
printf("Retrieved line of length %zu :", read);
int i = 0;
while(line[i] != '\0'){
if ( line[i] == ' '){
i++;
}
else if (i == 0){
newItem = malloc(sizeof(struct node));
int itemStorage = line[0] - '0';
newItem->next = NULL;
newItem->data = itemStorage;
G[itemStorage] = newItem;
printf("This is first Number:%d\n", itemStorage);
}
else if (line[i] != ' '){
struct node* addingItem = newItem;
while(addingItem->next != NULL){
addingItem = addingItem->next;
}
int itemStorage = line[i] - '0';
struct node* newConnection = malloc(sizeof(struct node));
addingItem->next = newConnection;
newConnection->data = itemStorage;
newConnection->next = NULL;
printf("This is character:%c\n", line[i]);
printf("This is connection:%i\n", itemStorage);
}
i++;
}
}
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
for(int printer = 1; printer<20; printer++){
printf("%d\n",G[printer]->data);
}
}
EDIT:
Just wanted to include file im reading from:
1 3 4
2 4
3 1 4
4 2 1 3
I am not sure why you want to have an array of pointers to node which you all allocate memory for at the beginning of your program without knowing how many nodes will be needed. Then you allocate memory again while reading from the file.
Given the constraints of not being allowed to use functions, thats how i'd read the file and build a list:
#include <stdlib.h>
#include <stdio.h>
typedef struct node_tag {
int value;
struct node_tag *next;
} node_t;
int main(void)
{
char const *filename = "test.txt";
FILE *input_file = fopen(filename, "r");
if (!input_file) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
// read from file and build a list:
node_t *head = NULL;
node_t *tail = NULL;
int value;
int result = EXIT_SUCCESS;
while (fscanf(input_file, "%d", &value) == 1) {
node_t *new_node = calloc(1, sizeof *new_node);
if (!new_node) {
fputs("Not enough memory :(\n\n", stderr);
result = EXIT_FAILURE;
goto glean_up;
}
new_node->value = value;
if (!head) { // there is no head yet so new_node becomes the head
head = tail = new_node; // which is also the lists tail
continue;
}
tail->next = new_node;
tail = new_node;
}
// print the list:
for (node_t *current_node = head; current_node; current_node = current_node->next)
printf("%d ", current_node->value);
putchar('\n');
clean_up:
fclose(input_file);
for (node_t *current_node = head, *temp; current_node; current_node = temp) {
temp = current_node->next;
free(current_node);
}
return result;
}
Ideally you'd write functions to manage the list:
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct node_tag {
int value;
struct node_tag *next;
} node_t;
typedef struct list_tag {
node_t *head;
node_t *tail;
} list_t;
void list_create(list_t *list)
{
list->head = list->tail = NULL;
}
bool list_push_back(list_t *list, int value)
{
node_t *new_node = calloc(1, sizeof *new_node);
if (!new_node)
return false;
new_node->value = value;
if (!list->head) {
list->head = list->tail = new_node;
return true;
}
list->tail->next = new_node;
list->tail = new_node;
return true;
}
void list_print(list_t *list)
{
for (node_t *current_node = list->head; current_node; current_node = current_node->next)
printf("%d ", current_node->value);
}
void list_free(list_t *list)
{
for (node_t *current_node = list->head, *temp; current_node; current_node = temp) {
temp = current_node->next;
free(current_node);
}
}
bool read_int(FILE *input_file, int *value)
{
return fscanf(input_file, "%d", value) == 1;
}
int main(void)
{
char const *filename = "test.txt";
FILE *input_file = fopen(filename, "r");
if (!input_file) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
// read from file and build a list:
list_t list;
list_create(&list);
int value;
while (read_int(input_file, &value)) {
if (!list_push_back(&list, value)) {
fputs("Not enough memory :(\n\n", stderr);
// clean up:
fclose(input_file);
list_free(&list);
return EXIT_FAILURE;
}
}
// print the list:
list_print(&list);
putchar('\n');
// clean up:
fclose(input_file);
list_free(&list);
}
Output:
1 3 4 2 4 3 1 4 4 2 1 3
When you hit a space character you iterate i. At the end of your loop you iterate i.
So when you hit a space character you iterate i twice, skipping the number and landing on the next space character.
Which is why you get the first number but miss the rest.
edit: removed getline() comments due to feedback from #swordfish. Current implementation is not problematic.

Can't Solve Infinite Loop

The program is supposed to take a user entered integer and convert it into binary through a stack of singly linked lists. I think it's either my toBin() function or my printStack() function that's causing the infinite loop.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct node_def node;
struct node_def
{
int val;
node *next;
};
node *head;
void push(int val);
void pop(node *head);
int top();
void printStack();
int toBin(int val);
int main()
{
int num = 0;
printf("Enter an integer: ");
scanf("%d", &num);
push(num);
toBin(num);
printStack();
return 0;
}
void push(int val)
{
node *new;
new = malloc(sizeof(node));
if (head == NULL)
{
head = malloc(sizeof(node));
head->next = NULL;
head->val = val;
}
else
{
new->next = head;
new->val = val;
head = new;
}
return;
}
void pop(node *head)
{
node *tmp;
if(head == NULL)
{
printf("Stack is Empty\n");
return;
}
else
{
tmp = head;
head = head->next;
free(tmp);
}
return;
}
int top()
{
return(head->val);
}
void printStack()
{
node *tmp;
tmp = head;
if(head == NULL)
{
return;
}
while(head != NULL)
{
printf("%d ", head->val);
head = head->next;
}
printf("\n");
return;
}
int toBin(int val)
{
pop(head);
int i = 1, remainder, binary;
while(val != 0)
{
remainder = val % 2;
binary = binary + remainder * i;
val = val / 2;
i = i * 10;
push(binary);
}
return val;
}
You run into an infinite loop due to not properly initialising your variables. In particular, you have no guarantees that your node* head will be initialised to NULL, or that your int variables in toBin() will be initialised to zero.
Always, always, always initialise your variables when programming in C/C++.
Fixing these bugs and removing unused code leaves us with:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_def node;
struct node_def
{
int val;
node *next;
};
/* Note that we are initialising the global variable to NULL. */
node *head = NULL;
void push(int val);
void printStack();
int toBin(int val);
int main()
{
int num = 0;
printf("Enter an integer: ");
scanf("%d", &num);
/* Removed push(num), as you're using parameters in the following call: */
toBin(num);
printStack();
return 0;
}
/* Changed printStack to use a tmp pointer to
traverse the stack without mutating it */
void printStack()
{
node* tmp = head;
while(tmp != NULL)
{
printf("%d ", tmp->val);
tmp = tmp->next;
}
printf("\n");
return;
}
int toBin(int val)
{
/* Removed pop() as you're getting val from parameters */
/* Also initialising remainder and binary variables */
int i = 1, remainder = 0, binary = 0;
while(val != 0)
{
remainder = val % 2;
binary = binary + remainder * i;
val = val / 2;
i = i * 10;
push(binary);
}
return val;
}
/* It's a stack so no if's are necessary for pushing */
void push(int val)
{
node *new = malloc(sizeof(node));
new->val = val;
new->next = head;
head = new;
return;
}

Malloc stack overflow

Guys below code works fine until size= 100000. However it gives me stack overflow error after size=200000.
How can i fix that ?
Is there some way to optimize it ?
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define SIZE 500000
// HELPER ARRAY FUNCTIONS
void check(int *arr)
{
int i = 0;
for (i = 0; i < SIZE - 1; i++)
{
if (arr[i]>arr[i + 1])
{
printf("Not sorted.\n");
return;
}
}
printf("Sorted.\n");
}
void fill_array(int *arr)
{
int i = 0;
for (i = 0; i < SIZE; i++)
arr[i] =rand()%100;
}
void print_array(int *arr)
{
int i;
for (i = 0; i < SIZE; i++)
printf("%d ", arr[i]);
printf("\n");
}
// NODE STRUCT
typedef struct BST_NODE
{
struct BST_NODE *left, *right;
int data;
}node;
// TREE FUNCTIONS
node* generate_node(int *value)
{
node *n = (node*)malloc(sizeof(node));
n->left = NULL;
n->right = NULL;
n->data = *value;
return n;
}
node* insert_node(node *n, int *value)
{
if (n == NULL)
return generate_node(value);
if (*value < n->data)
n->left = insert_node(n->left, value);
else
n->right = insert_node(n->right, value);
return n;
}
node* construct_BST(int *arr, node* n)
{
int i;
n = NULL;
for (i = 0; i < SIZE; i++)
n = insert_node(n, &arr[i]);
return n;
}
int s = 0;
void LVR(int *arr, node* n)
{
if (n != NULL)
{
LVR(arr, n->left);
arr[s] = n->data;
s++;
LVR(arr, n->right);
}
}
void tree_sort(int *arr)
{
node *root = (node*)malloc(sizeof(node));
root = construct_BST(arr, root);
LVR(arr, root);
}
// DRIVER PROGRAM
int main()
{
int *Array = (int*)malloc(sizeof(int)*SIZE);
fill_array(Array);
tree_sort(Array);
print_array(Array);
check(Array);
free(Array);
getchar();
return 0;
}
It gives an error at this part below:
node* generate_node(int *value)
{
node *n = (node*)malloc(sizeof(node));
n->left = NULL;
n->right = NULL;
n->data = *value;
return n;
}
As already pointed out by other people, the problem is that the depth of the tree will be SIZE in the worst case.
In the case of your code, since the value to hold is a value less than 100, you can suppress the depth of the tree by not creating a new node for the same value.
In case of the same value change to count up as follows.
#include <stdio.h>
#include <stdlib.h> //stdlib.h include malloc and free
#define SIZE 500000
typedef struct BST_NODE {
struct BST_NODE *left, *right;
int data;
int count;//Add for count
} node;
node* generate_node(int value){//just use int
node *n = (node*)malloc(sizeof(node));//C does not need to cast from void *.
n->right = n->left = NULL;
n->data = value;
n->count = 1;//set 1 at first time
return n;
}
node* insert_node(node *n, int value){
if(n == NULL)
return generate_node(value);
if(value < n->data)
n->left = insert_node(n->left, value);
else if (value > n->data)
n->right = insert_node(n->right, value);
else
n->count++;//Add count up
return n;
}
node* construct_BST(int *arr){//no need node *n as argument
int i;
node *n = NULL;
for (i = 0; i < SIZE; i++)
n = insert_node(n, arr[i]);
return n;
}
int s = 0;
void LVR(int *arr, node *n){
if (n != NULL){
int i;
LVR(arr, n->left);
for(i = 0; i < n->count; ++i)
arr[s++] = n->data;//Repeat as many times as count
LVR(arr, n->right);
}
}
void tree_free(node *n){
if(n){
tree_free(n->left);
tree_free(n->right);
free(n);
}
}
void tree_sort(int *arr){
node *root = construct_BST(arr);
s = 0;//Necessary for different calls
LVR(arr, root);
tree_free(root);//release tree
}
If you're getting a stack overflow, that means your function call stack is getting too deep. That can happen when building a binary search tree if the tree ends up being unbalanced.
Best case, your tree height will be O(log n), worst case it will be O(n). If you place items into the tree in sorted order, your binary tree will degenerate into a linked list and you'll hit the worst case.
For this particular example, you're generating random numbers from 0 to 99. You might get more randomize results if you increase the range of the numbers. So instead of using rand()%100, use something like rand()%10000. That might help keep the height of the tree down.
On an unrelated note, you have a memory leak. First, the initial node you allocate for the root of the tree gets overwritten, so you don't need it. Second, you never bother to free the tree structure.
You can take care of these as follows:
void free_tree(node *root)
{
if (root) {
free_tree(root->left);
free_tree(root->right);
free(root);
}
}
void tree_sort(int *arr)
{
node *root = NULL
root = construct_BST(arr, root);
LVR(arr, root);
free_tree(root);
}

Resources