printing tree results , segmentation error , insertion into tree - c

Here's the code , i run it with one example it works , but when it comes
to comparing i do not understand what's wrong ? , thanks in advance for
any help .I need to print dictionary texts properly (inserting , printing) , can not still come up with a solution , i mean using dictionary data structure like .
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
typedef struct Node_s {
char *element;
struct Node_s *left, *right;
} Node;
typedef struct {
Node *head;
} Table;
//Table *initialize();
//Node *createNode(const char *element);
Table *initialize() {
Table *tb = malloc(sizeof(Table)*1000);
tb->head = NULL;
return tb;
}
Node *createNode( char * element ) {
Node *temp = malloc(sizeof(temp));
temp->element = element ;
temp->left = temp->right = NULL;
return temp;
}
void insert(Table *temp, char *element) {
Node *nd = createNode(element);
Table * place = NULL;
Node *new = NULL;
int cmp = 0;
if(temp->head == NULL) {
temp->head= nd;
printf("empty ! \n");
return;
}
else {
Table *current = temp;
while (current!=NULL) {
cmp = strcmp(current->head->element,element);
if(cmp < 0) {
current->head= current->head->left;
}
else if(cmp > 0) {
current->head = current->head->right;
}
} //while
place = current;
new = nd;
if(cmp > 0 ) {
place->head->right = new ;
}
else if(cmp <0 ) {
place->head->left = new;
}
}
}
void print_table(Table *temp) {
if(temp!=NULL || !temp->head) return;
print_table(temp->head->left);
printf("%s \n",temp->head->element);
print_table(temp->head->right);
}
int main () {
Node * nd = NULL;
//nd->element = "key";
// nd = createNode("key");
Table *tb = initialize();
//tb->head = createNode("key");
//tb->head = createNode("key");
insert(tb, "table element1");
insert(tb, "table element2");
insert(tb, "table element2");
//nd = createNode("key1");
// print_table(t);
//printf("%s \n",nd->element);
print_table(tb);
// printf("%s \n",tb->head->element);
free(nd);
return 0;
}

There are a lot of potential bugs here, but your primary issue is in the following line of createNode:
Node *temp = malloc(sizeof(temp));
Here you're doing a sizeof(temp) and temp is a pointer. This means that you are only allocating enough memory for a pointer (usually 8 bytes). You are hence writing outside of allocating memory when using the left/right members of the heap allocated structure. The fix:
Node *temp = malloc(sizeof(Node));
// EXTRA: I also recommend that you verify that the allocation was successful
if (temp) {
temp->element = element ;
temp->left = temp->right = NULL;
}
return temp;
In printTable, you should also verify that temp itself isn't NULL as you are passing the function parameters that might be NULL:
if(!temp || !temp->head) return;
Also, remove the free(nd); at the end of main, as calling free() on unallocated heap memory corrupts the heap and typically leads to a segfault.

Your printing method crashes when reaching the last node on the left because it will call print_table(NULL) since there's nothing more on the left. After that when it executes the line
if(!temp->head) return;
You get a memory access violation because temp is NULL, you should also check if temp itself is NULL.
if( !temp || !temp->head ) return;
That should fix your problem.

One issue right away is on your second call to insert:
while (current != NULL) {
cmp = strcmp(current->head->element, element); // this line
You didn't check if current->head is NULL itself. According to what you've implemented, you use head as a sentinel, thus it can be NULL. However, your search loop totally forgot about this condition and assumes that head is never NULL.
Your loop doesn't seem fundamentally correct. You traverse the left, so what is supposed to happen if the left branch "runs out" (as it does now when you call insert the second time)?
In addition, your insert function has a memory leak. You potentially allocate 2 new nodes here:
Node *nd = createNode(element);
and here:
new = createNode(element);
Only one is stored while the other is leaked.
Another issue is that your tree does nothing in the while loop if the two items are equal. Two equal items results in an infinite loop:
while (current!=NULL)
{
cmp = strcmp(current->head->element,element);
if(cmp < 0)
current->head= current->head->left;
else if(cmp > 0)
current->head = current->head->right;
else
printf("these are equal ! \n"); // but we don't do anything with current!
}
If the goal is to not have duplicates, then you should exit this function if a duplicate is found. If the goal is to store duplicates, only test for < 0, anything else, goes on the right branch.

This might be what you are looking for.
It handles a doubly linked list
error checking is added
removed undesirable/unnecessary typedef's from struct definitions
corrected the logic to link in new nodes
avoided recursion in the printing of the linked list
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
struct Node
{
char *element;
struct Node *left;
struct Node *right;
};
// define the head pointer for the linked list
struct Node *head = NULL;
// struct Node *createNode(const char *element);
struct Node *createNode( char * element )
{
struct Node *pNewNode = NULL;
if( NULL == (pNewNode = malloc(sizeof(struct Node)) ) )
{ // then, malloc failed
perror( "malloc for new node failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
pNewNode->element = element ; // copies a char pointer
pNewNode->left = NULL;
pNewNode->right = NULL;
return pNewNode;
} // end function: createNode
void insert(char *element)
{
int cmp = 0;
// get ptr to first node in list
struct Node *pCurrentNode = head;
// create the node to be inserted into linked list
struct Node *pNewNode = createNode(element);
if (pCurrentNode == NULL)
{ // then list empty
head = pNewNode;
printf("added first node\n");
return;
}
// implied else, not first node
while (pCurrentNode->right)
{
cmp = strcmp(pCurrentNode->element,element);
if(cmp < 0)
{
// insert new node before current node
pNewNode->right = pCurrentNode;
pNewNode->left = pCurrentNode->left;
pCurrentNode->left = pNewNode;
(pNewNode->left)->right = pNewNode;
}
else if(cmp > 0)
{
// step to next node
pCurrentNode = pCurrentNode->right;
} // end if
// note: if data same, don't insert new node
} //while
if( pCurrentNode->right == NULL )
{ // then, reached end of list
// append new node to end of list
pNewNode->left = pCurrentNode;
pNewNode->right = NULL;
pCurrentNode->right = pNewNode;
} // end if
} // end function: insert
void print_table()
{
struct Node *pCurrentNode = head;
if( pCurrentNode == NULL ) return;
// implied else, list not empty
while( pCurrentNode )
{
printf("%s \n",pCurrentNode->element);
pCurrentNode = pCurrentNode->right;
} // end while
} // end function: print_table
void cleanup()
{
struct Node *pCurrentNode = head;
while( pCurrentNode )
{
pCurrentNode = pCurrentNode->right;
free( pCurrentNode->left );
}
} // end function: cleanup
int main ()
{
// exercise the insert function
insert("table element1"); // append first element
insert("table element2"); // append second element
insert("table element4"); // append third element
insert("table element3"); // insert forth element
insert("table element3"); // duplicate within list
insert("table element4"); // duplicate at end of list
print_table();
cleanup();
return 0;
} // end function: main

I tried a different implementation, it compiles and works, it does not allow duplicates.
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#define ELEMENT_SIZE 1024
typedef struct Node_s
{
char element[ELEMENT_SIZE];
struct Node_s *left, *right;
} Node;
Node * createNode(char *element)
{
Node *node = malloc(sizeof(Node));
node->left = NULL;
node->right = NULL;
memcpy(node->element, element, ELEMENT_SIZE);
return node;
}
void free_node(Node *node)
{
if(!node)
return;
free_node(node->left);
free_node(node->right);
free(node);
}
Node * insert(Node **head_ptr, char *element)
{
Node *head = *head_ptr;
if(head == NULL){
Node *node = createNode(element);
head = node;
*head_ptr = node;
return node;
}else{
int comp = strcmp(head->element, element);
if(comp < 0){
// go left
if(head->left == NULL){
// set element to be temp left
Node *node = createNode(element);
head->left = node;
return node;
}else{
return insert(&head->left, element);
}
}else if(comp > 0){
// go right
if(head->right == NULL){
// set element to be temp left
Node *node = createNode(element);
head->right = node;
return node;
}else{
return insert(&head->right, element);
}
}else{
// element exists
printf("Element \"%s\" already exists\n", element);
return NULL;
}
}
}
void print_table(Node *temp)
{
if(!temp)
return;
printf("%s \n",temp->element);
print_table(temp->left);
print_table(temp->right);
}
int main ()
{
Node *nd = NULL;
printf("Address of nd is %p\n", &nd);
Node *n1 = insert(&nd, "table element 1");
n1 = insert(&nd, "table element 2");
n1 = insert(&nd, "table element 3");
n1 = insert(&nd, "element 1");
n1 = insert(&nd, "element 2");
n1 = insert(&nd, "element 3");
n1 = insert(&nd, "alternative 1");
n1 = insert(&nd, "alternative 2");
n1 = insert(&nd, "alternative 3");
n1 = insert(&nd, "alternative 1");
n1 = insert(&nd, "alternative 2");
n1 = insert(&nd, "alternative 3");
print_table(nd);
free_node(nd);
return 0;
}

Related

Segmentation fault during insertion of node into linked list

I am attempting to alphabetize two separate lists in my add function: one that sorts the nodes by first names, and another that sorts by last names. I also have some logic that checks if a name is already in the list and if it is an error is printed and the list is returned unchanged. Like the title says, I am getting a segmentation fault here and am not sure why. It may be a pretty basic problem but I am new to C and especially new to linked lists.
Here is how the nodes are defined:
typedef struct node {
char *first;
char *last;
long number;
struct node *nextFirst;
struct node *nextLast;
} Node;
typedef struct mlist {
Node *headFirstName;
Node *headLastName;
} MultiLinkedList;
And here is my add function:
MultiLinkedList *add(MultiLinkedList *list, char *first, char *last, long num) {
// allocate a new node
Node *newNode = malloc ( sizeof(Node) );
newNode->first = malloc ( strlen(first) + 1 );
strcpy(newNode->first, first);
newNode->last = malloc ( strlen(last) + 1 );
strcpy(newNode->last, last);
newNode->number = num;
//make placeholder nodes
Node *a = list->headFirstName;
Node *b = list->headLastName;
// add this new node at the head of the "byFirst" list
if (strcmp(newNode->first, a->first) < 0) {
newNode->nextFirst = list->headFirstName;
list->headFirstName = newNode;
}
for (Node *i = list->headFirstName; i; i = i->nextFirst) {
// add after less alphabetical nodes
if (strcmp(newNode->first, i->first) > 0) {
newNode->nextFirst = i->nextFirst;
i->nextFirst = newNode;
}
// return error for duplicate name
if (strcmp(newNode->first, i->first) == 0 && strcmp(newNode->last, i->last) == 0) {
printf("That person is already in the list! Please try with a different name.\n");
}
}
// add this new node at the head of the "byLast" list
if (strcmp(newNode->last, b->last) < 0) {
newNode->nextLast = list->headLastName;
list->headLastName = newNode;
}
for (Node *j = list->headLastName; j; j = j->nextLast) {
// add after less alphabetical nodes
if (strcmp(newNode->last, j->last) > 0) {
newNode->nextLast = j->nextLast;
j->nextLast = newNode;
}
}
// return the multi-list object with updated or original head pointers
return list;
}
I figured out what my problem was. I had to add return list; to the end of each if statement otherwise the function attempts to perform every true statement; which causes the seg fault. In hindsight I'm surprised I didn't figure this out sooner.

Free a binary tree without recursion

refering to the question Deallocating binary-tree structure in C
struct Node{
Node *parent;
Node *next;
Node *child;
}
I tried to free a binary tree. The problem I have is the allocated objects are 5520 and the number of calls to the free functions is 2747. I don't know why, it should really free and iterate all over the nodes in the tree, here is the code that I use
int number_of_iterations =0;
int number_of_deletions =0;
void removetree(Node *node)
{
number_of_iterations++;
while(node != NULL)
{
Node *temp = node;
if(node->child != NULL)
{
node = node->child;
temp->child = node->next;
node->next = temp;
}
else
{
node = node->next;
remove(temp);
number_of_deletions++
}
}
}
Number of iteration is 5440 and the number of deletions is 2747.
New Fixed code: is that code correct ?
const Node *next(const Node *node)
{
if (node == NULL) return NULL;
if (node->child) return node->child;
while (node && node->next == NULL) {
node = node->parent;
}
if (node) return node->next;
return NULL;
}
for ( p= ctx->obj_root; p; p = next(p)) {
free(p);
}
If your nodes do indeed contain valid parent pointers, then the whole thing can be done in a much more compact and readable fashion
void removetree(Node *node)
{
while (node != NULL)
{
Node *next = node->child;
/* If child subtree exists, we have to delete that child subtree
first. Once the child subtree is gone, we'll be able to delete
this node. At this moment, if child subtree exists, don't delete
anything yet - just descend into the child subtree */
node->child = NULL;
/* Setting child pointer to null at this early stage ensures that
when we emerge from child subtree back to this node again, we will
be aware of the fact that child subtree is gone */
if (next == NULL)
{ /* Child subtree does not exist - delete the current node,
and proceed to sibling node. If no sibling, the current
subtree is fully deleted - ascend to parent */
next = node->next != NULL ? node->next : node->parent;
remove(node); // or `free(node)`
}
node = next;
}
}
This is a binary tree! It's confusing people because of the names you have chosen, next is common in a linked list but the types are what matters and you have one node referencing exactly two identical nodes types and that's all that matters.
Taken from here: https://codegolf.stackexchange.com/a/489/15982 which you linked to. And I renamed left to child and right to next :)
void removetree(Node *root) {
struct Node * node = root;
struct Node * up = NULL;
while (node != NULL) {
if (node->child != NULL) {
struct Node * child = node->child;
node->child = up;
up = node;
node = child;
} else if (node->next != NULL) {
struct Node * next = node->next;
node->child = up;
node->next = NULL;
up = node;
node = next;
} else {
if (up == NULL) {
free(node);
node = NULL;
}
while (up != NULL) {
free(node);
if (up->next != NULL) {
node = up->next;
up->next = NULL;
break;
} else {
node = up;
up = up->child;
}
}
}
}
}
I know that this is an old post, but i hope my answer helps someone in the future.
Here is my implementation of BinaryTree and it's operations in c++ without recursion, the logics can be easily implemented in C.
Each node owns a pointer to the parent node to make things easier.
NOTE: the inorderPrint() function used for printing out the tree's content uses recursion.
#include<iostream>
template<typename T>
class BinaryTree
{
struct node
{
//the binary tree node consists of a parent node for making things easier as you'll see below
node(T t)
{
value = t;
}
~node() { }
struct node *parent = nullptr;
T value;
struct node *left = nullptr;
struct node *right = nullptr;
};
node* _root;
//gets inorder predecessor
node getMinimum(node* start)
{
while(start->left)
{
start = start->left;
}
return *start;
}
/*
this is the only code that uses recursion
to print the inorder traversal of the binary tree
*/
void inorderTraversal(node* rootNode)
{
if (rootNode)
{
inorderTraversal(rootNode->left);
std::cout << rootNode->value<<" ";
inorderTraversal(rootNode->right);
}
}
int count;
public:
int Count()
{
return count;
}
void Insert(T val)
{
count++;
node* tempRoot = _root;
if (_root == nullptr)
{
_root = new node(val);
_root->parent = nullptr;
}
else
{
while (tempRoot)
{
if (tempRoot->value < val)
{
if (tempRoot->right)
tempRoot = tempRoot->right;
else
{
tempRoot->right = new node(val );
tempRoot->right->parent = tempRoot;
break;
}
}
else if (tempRoot->value > val)
{
if (tempRoot->left)
tempRoot = tempRoot->left;
else
{
tempRoot->left = new node(val);
tempRoot->left->parent = tempRoot;
break;
}
}
else
{
std::cout<<"value already exists";
count--;
}
}
}
}
void inorderPrint()
{
inorderTraversal(_root);
std::cout <<std::endl;
}
void Delete(T val)
{
node *tempRoot = _root;
//find the node with the value first
while (tempRoot!= nullptr)
{
if (tempRoot->value == val)
{
break;
}
if (tempRoot->value > val)
{
tempRoot = tempRoot->left;
}
else
{
tempRoot = tempRoot->right;
}
}
//if such node is found then delete that node
if (tempRoot)
{
//if it contains both left and right child replace the current node's value with inorder predecessor
if (tempRoot->right && tempRoot->left)
{
node inordPred = getMinimum(tempRoot->right);
Delete(inordPred.value);
count++;
tempRoot->value = inordPred.value;
}
else if (tempRoot->right)
{
/*if it only contains right child, then get the current node's parent
* check if the current node is the parent's left child or right child
* replace the respective pointer of the parent with the right child of the current node
*
* finally change the child's parent to the new parent
*/
if (tempRoot->parent)
{
if (tempRoot->parent->right == tempRoot)
{
tempRoot->parent->right = tempRoot->right;
}
if (tempRoot->parent->left == tempRoot)
{
tempRoot->parent->left = tempRoot->right;
}
tempRoot->right->parent = tempRoot->parent;
}
else
{
//if there is no parent then it's a root node
//root node should point to the current node's child
_root = tempRoot->right;
_root->parent = nullptr;
delete tempRoot;
}
}
else if (tempRoot->left)
{
/*
* same logic as we've done for the right node
*/
if (tempRoot->parent)
{
if (tempRoot->parent->right == tempRoot)
{
tempRoot->parent->right = tempRoot->left;
}
if (tempRoot->parent->left == tempRoot)
{
tempRoot->parent->left = tempRoot->left;
}
tempRoot->left->parent =tempRoot->parent ;
}
else
{
_root = tempRoot->left;
_root->parent = nullptr;
delete tempRoot;
}
}
else
{
/*
* if it's a leaf node, then check which ptr (left or right) of the parent is pointing to
* the pointer to be deleted (tempRoot)
* then replace that pointer with a nullptr
* then delete the (tempRoot)
*/
if (tempRoot->parent)
{
if (tempRoot->parent->right == tempRoot)
{
tempRoot->parent->right = nullptr;
}
else if (tempRoot->parent->left == tempRoot)
{
tempRoot->parent->left = nullptr;
}
delete tempRoot;
}
else
{
//if the leaf node is a root node ,then delete it and set it to null
delete _root;
_root = nullptr;
}
}
count--;
}
else
{
std::cout << "No element found";
}
}
void freeTree()
{
//the output it produces will be that of a preorder traversal
std::cout << "freeing tree:";
node* end=_root;
node* parent=nullptr;
while (end)
{
//go to the node with least value
if (end->left)
end = end->left;
else if (end->right)
{
//if it's already at the least value, then check if it has a right sub tree
//if it does then set it as "end" ptr so that the loop will check for the least node in this subtree
end = end->right;
}
else
{
//if it's a leaf node then it should be deleted and it's parent's (left or right pointer )
//should be safely set to nullptr
//then end should be set to the parent pointer
//so that it we can repeat the process for all other nodes that's left
std::cout << end->value<<" ";
parent = end->parent;
if (parent)
{
if (parent->left == end)
parent->left = nullptr;
else
parent->right = nullptr;
delete end;
}
else
{
delete end;
_root = nullptr;
}
count--;
end = parent;
}
}
}
~BinaryTree()
{
freeTree();
}
};
int main()
{
BinaryTree<int> bt;
bt.Insert(3);
bt.Insert(2);
bt.Insert(1);
bt.Insert(5);
bt.Insert(4);
bt.Insert(6);
std::cout << "before deletion:\n";
bt.inorderPrint();
bt.Delete(5);
bt.Delete(2);
bt.Delete(1);
bt.Delete(4);
std::cout << "after deletion:\n";
bt.inorderPrint();
bt.freeTree();
std::cout << "\nCount: " << bt.Count()<<"\n";
}
output:
before deletion:
1 2 3 4 5 6
after deletion:
3 6
freeing tree:6 3
Count: 0
freeing tree:
First to say is that if you try to solve a recursive problem in a non-recursive way, you'll run into trouble.
I have seen a wrong answer selected as the good one, so I'll try to show my approach:
I'll begin using pointer references instead of plain pointers, as passing a root pointer reference makes it easier to detect (and update) the pointers to the root node. So the interface to the routine will be:
void delete_tree(struct node * * const ref);
It represents a reference to the pointer that points to the root node. I'll descend to the node and, if one of child or next is NULL then this node can be freely eliminated by just making the referenced pointer to point to the other link (so I'll not lose it). If the node has two children (child and next are both != NULL) then I cannot delete this node until one of the branches has collapsed, and then I select one of the branches and move the reference (I declared the ref parameter const to assure I don't modify it, so I use another moving reference for this)
struct node **moving_reference;
Then, the algorithm follows:
void tree_delete(struct node ** const static_ref)
{
while (*static_ref) {
struct node **moving_ref = static_ref;
while (*moving_ref) {
struct node *to_be_deleted = NULL;
if ((*moving_ref)->child && (*moving_ref)->next) {
/* we have both children, we cannot delete until
* ulterior pass. Just move the reference. */
moving_ref = &(*moving_ref)->child;
} else if ((*moving_ref)->child) {
/* not both != NULL and child != NULL,
* so next == NULL */
to_be_deleted = *moving_ref;
*moving_ref = to_be_deleted->child;
} else {
/* not both != NULL and child == NULL,
* so follow next */
to_be_deleted = *moving_ref;
*moving_ref = to_be_deleted->next;
} /* if, else if */
/* now, delete the unlinked node, if available */
if (to_be_deleted) node_delete(to_be_deleted);
} /* while (*moving_ref) */
} /* while (*static_ref) */
} /* delete_tree */
I have included this algorithm in a complete example, showing you the partial trees and the position of moving_ref as it moves through the tree. It also shows the passes needed to delete it.
#include <stdio.h>
#include <stdlib.h>
#define N 100
#define D(x) __FILE__":%d:%s: " x, __LINE__, __func__
#define ASSERT(x) do { \
int res; \
printf(D("ASSERT: (" #x ") ==> %s\n"), \
(res = (int)(x)) ? "TRUE" : "FALSE"); \
if (!res) exit(EXIT_FAILURE); \
} while (0)
struct node {
int key;
struct node *child;
struct node *next;
}; /* struct node */
struct node *node_alloc(void);
void node_delete(struct node *n);
/* This routine has been written recursively to show the simplicity
* of traversing the tree when you can use recursive algorithms. */
void tree_traverse(struct node *n, struct node *p, int lvl)
{
while(n) {
printf(D("%*s[%d]\n"), lvl<<2, p && p == n ? ">" : "", n->key);
tree_traverse(n->child, p, lvl+1);
n = n->next;
} /* while */
} /* tree_traverse */
void tree_delete(struct node ** const static_ref)
{
int pass;
printf(D("BEGIN\n"));
for (pass = 1; *static_ref; pass++) {
struct node **moving_ref = static_ref;
printf(D("Pass #%d: Considering node %d:\n"),
pass, (*moving_ref)->key);
while (*moving_ref) {
struct node *to_be_deleted = NULL;
/* print the tree before deciding what to do. */
tree_traverse(*static_ref, *moving_ref, 0);
if ((*moving_ref)->child && (*moving_ref)->next) {
printf(D("Cannot remove, Node [%d] has both children, "
"skip to 'child'\n"),
(*moving_ref)->key);
/* we have both children, we cannot delete until
* ulterior pass. Just move the reference. */
moving_ref = &(*moving_ref)->child;
} else if ((*moving_ref)->child) {
/* not both != NULL and child != NULL,
* so next == NULL */
to_be_deleted = *moving_ref;
printf(D("Deleting [%d], link through 'child' pointer\n"),
to_be_deleted->key);
*moving_ref = to_be_deleted->child;
} else {
/* not both != NULL and child != NULL,
* so follow next */
to_be_deleted = *moving_ref;
printf(D("Deleting [%d], link through 'next' pointer\n"),
to_be_deleted->key);
*moving_ref = to_be_deleted->next;
} /* if, else if */
/* now, delete the unlinked node, if available */
if (to_be_deleted) node_delete(to_be_deleted);
} /* while (*moving_ref) */
printf(D("Pass #%d end.\n"), pass);
} /* for */
printf(D("END.\n"));
} /* delete_tree */
struct node heap[N] = {0};
size_t allocated = 0;
size_t deleted = 0;
/* simple allocation/free routines, normally use malloc(3). */
struct node *node_alloc()
{
return heap + allocated++;
} /* node_alloc */
void node_delete(struct node *n)
{
if (n->key == -1) {
fprintf(stderr,
D("doubly freed node %ld\n"),
(n - heap));
}
n->key = -1;
n->child = n->next = NULL;
deleted++;
} /* node_delete */
/* main simulation program. */
int main()
{
size_t i;
printf(D("Allocating %d nodes...\n"), N);
for (i = 0; i < N; i++) {
struct node *n;
n = node_alloc(); /* the node */
n->key = i;
n->next = NULL;
n->child = NULL;
printf(D("Node %d"), n->key);
if (i) { /* when we have more than one node */
/* get a parent for it. */
struct node *p = heap + (rand() % i);
printf(", parent %d", p->key);
/* insert as a child of the parent */
n->next = p->child;
p->child = n;
} /* if */
printf("\n");
} /* for */
struct node *root = heap;
ASSERT(allocated == N);
ASSERT(deleted == 0);
printf(D("Complete tree:\n"));
tree_traverse(root, NULL, 0);
tree_delete(&root);
ASSERT(allocated == N);
ASSERT(deleted == N);
} /* main */
Why not just do this recurisively?
void removetree(Node *node) {
if (node == NULL) {
return;
}
number_of_iterations++;
removetree(node->next);
removetree(node->child);
free(node);
number_of_deletions++;
}
The implementation does not work for a tree with root 1, which has a single child 2.
NodeOne.parent = null
NodeOne.next = null
NodeOne.child = NodeTwo
NodeTwo.parent = null
NodeTwo.next = null
NodeTwo.child = null
Execution of Removetree(NodeOne) will not call remove on NodeOne.
I would do
void removeTree(Node *node){
Node *temp;
while (node !=NULL){
if (node->child != NULL) {
removeTree(node->child);
}
temp = node;
node = node->next;
free(temp);
}
}
Non-recursive version:
void removeTree(Node *node){
Node *temp;
while (node !=NULL){
temp = node;
while(temp != node) {
for(;temp->child == NULL; temp = temp->child); //Go to the leaf
if (temp->next == NULL)
free(temp); //free the leaf
else { // If there is a next move it to the child an repeat
temp->child = temp->next;
temp->next = temp->next->next;
}
}
node = temp->next; // Move to the next
free(temp)
}
}
I think this should work
You are freeing only subtrees, not parent nodes. Suppose child represents the left child of the node and next is the right child. Then, your code becomes:
struct Node{
Node *parent;
Node *right;
Node *left;
}
int number_of_iterations =0;
int number_of_deletions =0;
void removetree(Node *node)
{
number_of_iterations++;
while(node != NULL)
{
Node *temp = node;
if(node->left != NULL)
{
node = node->left;
temp->left = node->right;
node->right = temp;
}
else
{
node = node->right;
remove(temp);
number_of_deletions++
}
}
}
Each time your while loop finishes one iteration, a left sub-node will be left without a pointer to it.
Take, for example the following tree:
1
2 3
4 5 6 7
When node is the root node, the following happens
node is pointing to '1'
temp is pointing to '1'
node now points to '2'
temp->left now points to '5'
node->right now points to '1'
In the next iteration, you begin with
node pointing to '2' and temp also. As you can see, you did not remove node '1'. This will repeat.
In order to fix this, you might want to consider using BFS and a queue-like structure to remove all the nodes if you want to avoid recursion.
Edit
BFS way:
Create a Queue structure Q
Add the root node node to Q
Add left node of node to Q
Add right node of node to Q
Free node and remove it from Q
Set node = first element of Q
Repeat steps 3-6 until Q becomes empty
This uses the fact that queue is a FIFO structure.
Code that was proposed by #AnT is incorrect, because it frees node right after traversing and freeing its left subtree but before doing the same with the right subtree. So, on ascending from the right subtree we'll step on the parent node that was already freed.
This is a correct approach, in C89. It still requires the parent links, though.
void igena_avl_subtree_free( igena_avl_node_p root ) {
igena_avl_node_p next_node;
{
while (root != NULL) {
if (root->left != NULL) {
next_node = root->left;
root->left = NULL;
} else if (root->right != NULL) {
next_node = root->right;
root->right = NULL;
} else {
next_node = root->parent;
free( root );
}
root = next_node;
}
}}
Taken directly from my own project Gena.

Mergesort on a linked-list using only one function, segmentation fault

I need to implement the function: struct listnode * mergesort(struct listnode *data)
My professor provided the main() function testing code. I only need to submit the mergesort function. He told us to do it in C or C++ but the test code main() he gave us is in C.
This is my code right now:
I can compile it but when I run it, it crashes. I checked debugger and it gave me segmentation fault. I am also not really sure if this function is correct since I can't get past the testing point in the main().
#include <stdio.h>
#include <stdlib.h>
struct listnode { struct listnode * next;
long value; } ;
struct listnode * mergesort(struct listnode *data)
{ int temp, finished = 0;
struct listnode *tail, *head, *ahead, *bhead, *atail, *btail;
if ( data == NULL )
return;
//Split
ahead = atail = head = data; // first item
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
atail = atail->next;
btail = btail->next;
if( btail->next != NULL)
btail = btail->next;
}
bhead = atail->next; // disconnect the parts
atail->next = NULL;
//sort
mergesort(ahead);
mergesort(bhead);
//merge
if(ahead->value <= bhead->value) // set the head of resulting list
head = tail = ahead, ahead = ahead->next;
else
head = tail = bhead, bhead = bhead->next;
while(ahead && bhead)
if(ahead->value <= bhead->value) // append the next item
tail = tail->next = ahead, ahead = ahead->next;
else
tail = tail->next = bhead, bhead = bhead->next;
if(ahead != NULL)
tail->next = ahead;
else
tail->next = bhead;
return(head);
}
int main(void)
{
long i;
struct listnode *node, *tmpnode, *space;
space = (struct listnode *) malloc( 500000*sizeof(struct listnode));
for( i=0; i< 500000; i++ )
{ (space + i)->value = 2*((17*i)%500000);
(space + i)->next = space + (i+1);
}
(space+499999)->next = NULL;
node = space;
printf("\n prepared list, now starting sort\n");
node = mergesort(node);
printf("\n checking sorted list\n");
for( i=0; i < 500000; i++)
{ if( node == NULL )
{ printf("List ended early\n"); exit(0);
}
if( node->value != 2*i )
{ printf("Node contains wrong value\n"); exit(0);
}
node = node->next;
}
printf("Sort successful\n");
exit(0);
}
if ( data == NULL )
return;
You should return NULL.
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
If btail is set to head->next. If head->next is NULL, you're trying to check in the loop NULL->next != NULL which isn't a thing.
if( btail->next != NULL)
btail = btail->next;
}
You need to check if btail is NULL before you check ->next. Just above you are setting btail = btail->next; so it could be set to NULL.
Also the loop above has the same issue, you need to check null before you do stuff with next.
There may be issues with the below code, but the above code needs way more error checking.
Example function to merge two already sorted lists using pointer to pointer. Since your'e only allowed a single function, you'll have to merge this logic into your mergesort() function. If this is homework, it may seem like you had too much help, but I'm not sure how else to explain the ideas shown in this example.
NODE * MergeLists(NODE *pSrc1, NODE *pSrc2)
{
NODE *pDst = NULL; /* destination head ptr */
NODE **ppDst = &pDst; /* ptr to head or prev->next */
while(1){
if(pSrc1 == NULL){
*ppDst = pSrc2;
break;
}
if(pSrc2 == NULL){
*ppDst = pSrc1;
break;
}
if(pSrc2->data < pSrc1->data){ /* if src2 < src1 */
*ppDst = pSrc2;
pSrc2 = *(ppDst = &(pSrc2->next));
continue;
} else { /* src1 <= src2 */
*ppDst = pSrc1;
pSrc1 = *(ppDst = &(pSrc1->next));
continue;
}
}
return pDst;
}

Write a function that rearranges a linked list to put the nodes in even positions after the nodes in odd positions in the list

Write a function that rearranges a linked list to put the nodes in even positions after the nodes in odd positions in the list, preserving the relative order of both the evens and the odds.
I found this problem in the book Algorithm in c writtern by Sedgewick. I have tried but failed. I trid to put all nodes in even positions on another linked list. It's grateful for you to help me. A good idea is enough. Thanks :).
This is my Code in C.
/*
* File: rearranges.c <Exercise 3.36>
* Note: Write a function that rearranges a linked list to put the nodes in even
* positions after the nodes in odd positions in the list, preserving the
* relative order of both the evens and the odds.
* NOTICE: I think it's necessary to use linked list with a dummy head.
* Time: 2013-10-26 10:58
*/
#include <stdio.h>
#include <stdlib.h>
#define LEN 11
typedef struct node *link;
struct node {
int item;
link next;
};
/* Traverse a linked list with a dummy head. */
void traverse(link t) {
link x = t->next;
while (x != NULL) {
printf("%d ", x->item);
x = x->next;
}
putchar('\n');
}
/* Detach even positon nodes from a linked list. */
link detach(link t) {
link u = malloc(sizeof(*u));
link x = t, y = u;
/* x is odd position node. We should ensure that there's still one even
* position node after x. */
while (x != NULL && x->next != NULL) {
y->next = x->next;
x->next = x->next->next;
x = x->next;
y = y->next;
y->next = NULL;
}
return u;
}
/* Combine two linked list */
link combine(link u, link t) {
link x = u;
link y = t->next;
while (y != NULL) {
link n = y->next;
y->next = x->next;
x->next = y;
x = x->next->next;
y = n;
}
return u;
}
/* The function exchanges the position of the nodes in the list. */
link rearranges(link t) {
link u = detach(t);
link v = combine(u, t);
return v;
}
int main(int argc, char *argv[]) {
int i;
link t = malloc(sizeof(*t));
link x = t;
for (i = 0; i < LEN; i++) {
x->next = malloc(sizeof(*x));
x = x->next;
x->item = i;
x->next = NULL;
}
traverse(t);
traverse(rearranges(t));
return 0;
}
curr=head;
end=lastOfList;//last node if size of list is odd or last-1 node
for(int i=1;i<=listSize()/2;i++)
{
end->next=curr->next;
end=end->next;
end->next=null;
if(curr->next!=null)
if((curr->next)->next!=null)
curr->next=(curr->next)->next;
curr=curr->next;
}
You can implement a recursive solution where each call returns an updated node that will serve as the new next reference for the upper caller. We just have to go down the list until we find the last element, and then move every even node to the end of the list, and update the reference to the last element. Here's my solution (please try to do it yourself before looking at my and other solutions):
struct node {
int val;
struct node *next;
};
struct node *reorder_aux(struct node *l, int count, struct node **last);
struct node *reorder(struct node *l) {
struct node *x;
if (l == NULL)
return NULL;
return reorder_aux(l, 1, &x);
}
struct node *reorder_aux(struct node *l, int count, struct node **last) {
struct node *n;
if (l->next == NULL) {
*last = l;
return l;
}
n = reorder_aux(l->next, count+1, last);
if (count & 1) {
l->next = n;
return l;
}
else {
(*last)->next = l;
l->next = NULL;
*last = l;
return n;
}
}
At each step, if the current node l is an even node (as determined by count), then we append this node to the end, and tell the upper caller that its next pointer shall be updated to our next (because our next will be an odd node). In case we're an odd node, we just have to update our next pointer to whatever the recursive call returned (which will be a pointer to an odd node), and return the current node, since we will not move ourselves to the end of the list.
It's a nice exercise!
#include <stdio.h>
struct list {
struct list *next;
int ch;
};
void swap_odd_even (struct list **pp)
{
struct list *one, *two ;
for( ; (one = *pp) ; pp = &one->next) {
two = one->next;
if (!two) break;
*pp = two;
one->next = two->next;
two->next = one;
}
}
struct list arr[] =
{ {arr+1, 'A'} , {arr+2, 'B'} , {arr+3, 'C'} , {arr+4, 'D'}
, {arr+5, 'E'} , {arr+6, 'F'} , {arr+7, 'G'} , {arr+8, 'H'}
, {arr+9, 'I'} , {arr+10, 'J'} , {arr+11, 'K'} , {arr+12, 'L'}
, {arr+13, 'M'} , {arr+14, 'N'}, {arr+15, 'O'} , {arr+16, 'P'}
, {arr+17, 'Q'} , {arr+18, 'R'} , {arr+19, 'S'} , {arr+20, 'T'}
, {arr+21, 'U'} , {arr+22, 'V'}, {arr+23, 'W'} , {arr+24, 'X'}
, {arr+25, 'Y'} , {NULL, 'Z'} };
int main (void) {
struct list *root , *ptr;
root = arr;
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
printf( "Swap\n" );
swap_odd_even ( &root);
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
return 0;
}
In the following, every time swap_nodes is called another odd sinks to the last sunk odd. The evens are grouped together on each iteration and they bubble up to the end of the list. Here is an example:
/*
[0]-1-2-3-4-5
1-[0-2]-3-4-5
1-3-[0-2-4]-5
1-3-5-[0-2-4]
*/
#include <stdio.h>
#include <stdlib.h>
#define LIST_LENGTH 10
struct node{
int id;
struct node *next;
};
void print_list(struct node *current)
{
while(NULL != current){
printf("node id = %d\n",current->id);
current = current->next;
}
printf("Done\n");
}
struct node *swap_nodes(struct node *head_even, struct node *tail_even, struct node *next_odd)
{
tail_even->next = next_odd->next;
next_odd->next = head_even;
return next_odd;
}
struct node *reorder_list(struct node *head)
{
struct node *head_even;
struct node *tail_even;
struct node *next_odd;
struct node *last_odd;
if(NULL == head->next){
return head;
}
head_even = head;
tail_even = head;
next_odd = head->next;
last_odd = head->next;
head = swap_nodes(head_even, tail_even, next_odd);
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
while (NULL != tail_even->next) {
next_odd = tail_even->next;
last_odd->next = swap_nodes(head_even, tail_even, next_odd);
last_odd = last_odd->next;
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
}
return head;
}
int main(void)
{
int i;
struct node *head = (struct node *) malloc(LIST_LENGTH*sizeof(struct node));
struct node *mem = head;
if(NULL == head){
return -1;
}
struct node *current = head;
for(i=0;i<LIST_LENGTH-1;i++){
current->next = current + 1;
current->id = i;
current = current->next;
}
current->next = NULL;
current->id = i;
head = reorder_list(head);
print_list(head);
free(mem);
return 0;
}

Deleting first node in linked list has problems

I'm implementing a linked list and it needs to have a function that when given a head of a linked list and a cstring, it finds and deletes a node whose value is the cstring.
typedef struct node
{
char entry[21];
struct node* next;
} node;
/*returns true if node with phrase value found, otherwise false*/
bool findAndRemove(node* root, char phrase[21])
{
if(root != NULL)
{
node* previous = NULL;
while(root->next != NULL)
{
if(strcmp(root->entry, phrase) == 0)//found
{
if(previous == NULL)//node to delete is at head
{
node* tmp = root;
root = root->next;
free(tmp);
return true;
}
previous->next = root->next;
free(root);
return true;
}
previous = root;
root = root->next;
}
return false;
}
}
It works alright but when deleting the head some garbage gets printed out. What is happening and how can I fix this? Do I have any memory leaks? Out of curiosity is the term "root" or "head" more commonly used for the first node in a linked list?
The first thing to realise is that removing an element from a linked list involves changing exactly one pointer value: the pointer that points at us. This can be the external head pointer that points to the first list element, or one of the ->next pointers inside the list. In both cases that pointer needs to be changed; its new value should become the value of the ->next pointer of the node to be deleted.
In order to change some object (from within a function) we need a pointer to it. We need to change a pointer, so we will need a pointer to pointer.
bool findAndRemove1(node **ptp, char *phrase)
{
node *del;
for( ;*ptp; ptp = &(*ptp)->next) {
if( !strcmp((*ptp)->entry, phrase) ) { break; } //found
}
/* when we get here, ptp either
** 1) points to the pointer that points at the node we want to delete
** 2) or it points to the NULL pointer at the end of the list
** (in the case nothing was found)
*/
if ( !*ptp) return false; // not found
del = *ptp;
*ptp = (*ptp)->next;
free(del);
return true;
}
The number of if conditions can even be reduced to one by doing the dirty work in the loop,and returning from the loop but that would be a bit of a hack:
bool findAndRemove2(node **ptp, char *phrase)
{
for( ;*ptp; ptp = &(*ptp)->next) {
node *del;
if( strcmp((*ptp)->entry, phrase) ) continue; // not the one we want
/* when we get here, ptp MUST
** 1) point to the pointer that points at the node we want to delete
*/
del = *ptp;
*ptp = (*ptp)->next;
free(del);
return true;
}
return false; // not found
}
But what if the list is not unique, and we want to delete all the nodes that satisfy the condition? We just alter the loop logic a bit and add a counter:
unsigned searchAndDestroy(node **ptp, char *phrase)
{
unsigned cnt;
for( cnt=0 ;*ptp; ) {
node *del;
if( strcmp((*ptp)->entry, phrase) ) { // not the one we want
ptp = &(*ptp)->next;
continue;
}
/* when we get here, ptp MUST point to the pointer that points at the node we wish to delete
*/
del = *ptp;
*ptp = (*ptp)->next;
free(del);
cnt++;
}
return cnt; // the number of deleted nodes
}
Update: and a driver program to test it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct list {
struct list *next;
char entry[20];
} node;
void node_add( node **ptp, char *str)
{
node *new;
for ( ; *ptp; ptp = &(*ptp)->next) {
if (strcmp ((*ptp)->entry, str) < 0) continue;
}
new = malloc (sizeof *new);
strcpy(new->entry, str);
new->next = *ptp;
*ptp = new;
}
int main (void)
{
node *root = NULL;
unsigned cnt;
node_add (& root, "aaa" );
node_add (& root, "aaa" );
node_add (& root, "bbb" );
node_add (& root, "ccc" );
node_add (& root, "aaa" );
cnt = seachAndDestroy( &root, "bbb" );
printf("Cnt(bbb) := %u\n", cnt );
cnt = seachAndDestroy( &root, "ccc" );
printf("Cnt(ccc) := %u\n", cnt );
cnt = seachAndDestroy( &root, "aaa" );
printf("Cnt(aaa) := %u\n", cnt );
printf("Root now = %p\n", (void*) root );
return 0;
}
And the output:
plasser#pisbak:~/usenet$ ./a.out
Cnt(bbb) := 1
Cnt(ccc) := 1
Cnt(aaa) := 3
Root now = (nil)
You are changing the root inside the function, thus you need to pass a double pointer:
bool findAndRemove(node** root, char phrase[21])
{
node* iterate = *root;
if(root != NULL && *root != NULL)
{
node* previous = NULL;
while(iterate->next != NULL)
{
if(strcmp(iterate->entry, phrase) == 0)//found
{
if(previous == NULL)//node to delete is at head
{
node* tmp = iterate;
*root = iterate->next;
free(tmp);
return true;
}
previous->next = iterate->next;
free(iterate);
return true;
}
previous = iterate;
iterate = iterate->next;
}
return false;
}
}
You construct a list by pointing to the first node.
Then you delete the first node, but do not update the pointer to the list to point to the second one
Just make your function check if you are deleting the first node, and always return a pointer to the first pointer of the final list. Alternatively, instead of node *root parameter, pass node **root so you can modifiy the reference in your function (although I don't like this way of working).

Resources