I am having problems with my huffman tree; when I try to build it I get the nodes in the wrong place. For example, I want my node of weight 2 (with children i:1 and n:1) to go in between a node of m:2 and space:3 but instead it goes right after the previous node that I put in (2 with children of e:1 and g:1).
My question is: how do I insert a node with two children into a huffman tree (I am using a linked list) by priority of both it's weight (aka the sum of both its children) and the symbols of the children (i.e. the right child 'n' comes before the other right child of 'g').
Thanks for your help!
EDIT: also, how can I print off the codes of the tree in alphabetical order; right now I have them printing off by rightmost tree to leftmost
Here is my insert function...
struct node* insert(struct node* head, struct node* temp)
{
struct node* previous = NULL;
struct node* current = head;
printf("entering insert function\n");
// finds the previous node, where we want to insert new node
while (temp->freq > current->freq && current->next != NULL)
{
printf("traversing: tempfreq is %lu and currentfreq is %lu\n", temp->freq, current->freq);
previous = current;
current = current->next;
}
if (current->next == NULL)
{
printf("hit end of list\n");
temp = current->next;
}
else
{
printf("inserting into list\n");
temp->next = current;
previous->next = temp;
}
return head;
}
You've got the insertion wrong when you hit the end of the list. This:
temp = current->next;
should be the other way round, otherwise you just assign NULL to a temporary variable, which won't do anything to your list.
But I think that you also got your special cases wrong. The special case is not "insert at the end", but "insert a new head". Your code will fail if head == NULL. (This might not happen, because you have already a list of nodes without children and you remove nodes until only one node is left, but still.)
A better implementation might therefore be:
struct node *insert(struct node *head, struct node *temp)
{
struct node *previous = NULL;
struct node *current = head;
while (current && temp->freq > current->freq) {
previous = current;
current = current->next;
}
if (previous == NULL) {
temp->next = head;
return temp;
}
temp->next = current;
previous->next = temp;
return head;
}
Note how this code never derefeneces current or previous when they are NULL. Your special case "insert at the end" is handled by the regular code when current == NULL.
Edit: Concerning your request to print the nodes in alphabetical order: There are many possibilities to do that. One is to add a char buffer to your structure that contains the encoding for the letter:
struct node {
int value;
unsigned long freq;
struct node *next;
struct node *left;
struct node *right;
char code[32];
};
Then you create an "alphabet", i.e a list of 256 pointers to nodes of your Huffman tree, initially all null. (You'll need that alphabet for encoding anyways.)
struct node *alpha[256] = {NULL};
Then traverse your tree, pass a temporary char buffer and assign nodes to your alphabet as appropriate:
void traverse(struct node *n, int level, char buf[], struct node *alpha[])
{
if (n == NULL) return;
if (n->value) {
alpha[n->value] = n;
strcpy(n->code, buf);
} else {
buf[level] = '0';
traverse(n->left, level + 1, buf, alpha);
buf[level] = '1';
traverse(n->right, level + 1, buf, alpha);
}
}
When the node has a value, i.e. is childless, the value (ASCII code) is assigned to the alphabet, so that alpha['a'] points to the node with value 'a'. Note that the alphabet does not create nodes, it points to existing nodes.
Finally, print the alphabet:
char buf[32];
traverse(head, 0, buf, alphabet);
for (i = 0; i < 256; i++) {
if (alpha[i] != NULL) {
printf("%c: %s\n", alpha[i]->value, alpha[i]->code);
}
}
Please note that 32 is n arbitrary value that is chosen to be high enough for the example. In a real tree, memory for the code might be allocated separately.
Related
I am trying to print the values stored in a linked list but i'm running into a infinite loop.Please could some one tell me what is wrong with my code. I am able to successfully collect the data of the nodes but when printing the list i run into a continuous loop. Any help would be greatly appreciated. Thanks in advance
#include <stdio.h>
#include <stdlib.h>
struct node {
int data; //4 bytes
struct node *next; // 4bytes 32 bit and 8 bytes i 64bit cp
};
int main(){
struct node *head,*newnode,*temp;
head = NULL ;
temp = head;
int count=0, choice=1;
while(choice){
newnode = (struct node *)malloc(sizeof(struct node));
printf("Enter data:");
scanf("%d",&newnode-> data);
newnode->next = head;
if(head == 0){
head = temp = newnode;
}
else{
temp->next = newnode;
temp = newnode;
}
printf(" %d ",temp->data);
printf("Do you want to continue? 0/1");
scanf("%d",&choice);
}
int i = 0;
temp = head;
while( temp!=NULL){
printf("%d ",temp->data);
temp=temp->next;
}
}
I doubt it's within the scope of the homework problem in question, but it's really helpful to break linked list tasks down into smaller problems.
We start with this node definition:
struct node {
int data; //4 bytes
struct node *next; // 4bytes 32 bit and 8 bytes i 64bit cp
};
Which I'm going to typedef to make my life slightly easier.
typedef struct node {
int data; //4 bytes
struct node *next; // 4bytes 32 bit and 8 bytes i 64bit cp
} node_t;
Let's find the last node for a given head. We'll create a node_t pointer called current and use it to walk the list until it's at the last node. We'll know it's the last because its next member will be NULL. Of course, if head is NULL, then we'll just return NULL immediately.
node_t *last_node(node_t *head) {
if (head == NULL) {
return NULL;
}
node_t *current;
for (current = head; current->next != NULL; current = current->next);
return current;
}
Now, let's add a value to a list with a given head. We can provide a shortcut by returning a pointer the new last node. We'll also short-circuit a lot of work if head is NULL.
Otherwise we'll get the last node using the last_node function we defined, set its next to the new node, and return a pointer to the new node.
node_t *add_to_list(node_t *head, int value) {
node_t * new_node = malloc(sizeof(node_t));
new_node->data = value;
new_node->next = NULL;
if (head == NULL) {
return new_node;
}
node_t *last = last_node(head);
last->next = new_node;
return new_node;
}
And finally we can write a function to print the list. Given that you've already seen walking the list, this should look pretty familiar.
void print_list(node_t *head) {
for (node_t *current = head;
current->next != NULL;
current = current->next) {
printf("%d ", current->data);
}
}
Breaking down big problems into smaller problems is crucial. Practice it!
When you create a new node, you set it's "next" node to the head node. That's how the loop is made.
Set it to NULL.
And afterwards you set the new node as the "current node's next node" and the "current node" as well.
I believe you wanted to set it to temp's next node and then move the temp onto it's next node.
Also please don't compare head with 0... If you expect it to be NULL compare to NULL.
In our class right now we're covering nodes and linked lists, and are working on our first linked list program.
We've been given the following guidelines by the teacher:
Make sure your main function will accept 10 characters from STDIN and create a linked list with those characters (so your nodes will have a char member). Then, add an additional function called reverse. The purpose of the reverse function will be to create a copy of the linked list with the nodes reversed. Finally, print off the original linked list as well as the reversed linked list.
I've gotten it all written out, and I've compiled it with no errors - but the program doesn't work as intended, and I'm not entirely sure why. I'm sure it has something to do with how I've set up the pointers to "walk" the nodes - as the debug I put in shows it looping twice per user input letter. Specifications are that we're only supposed to use one function, and we pass a Node* to the function, and it returns the same. The function cannot print out anything - only make the second list that is a reverse of the first.
Any help would be greatly appreciated, I'm not terribly good at this yet and I'm sure I've made some rather silly mistakes.
#include <stdio.h>
#include <stdlib.h>
//struct declaration with self-reference to make a linked list
struct charNode {
char data;
struct charNode *nextPtr;
struct prevNode *prevPtr;
};
typedef struct charNode Node; //makes Node an alias for charNode
typedef Node *NodePtr; //makes NodePtr an alias for a pointer to Node (I think?)
//function declaration for a reverse function
Node* reverse(Node *stPtr);
int main(void)
{
//main function takes 10 letters and puts them in a linked list
//after that, it calls the reverse function to create a reversed list of those characters
//lastly it prints both lists
NodePtr newNode = NULL;
char input;
Node* revStart;
unsigned int counter = 0;
printf("Enter 10 letters to make a list: ");
NodePtr currentPtr = NULL; //sets currentPointer to startNode.
NodePtr previousPtr = NULL; //set previousPointer to null to start
while(counter<= 10)
{
scanf("%c", &input); //gather next letter
NodePtr newNode = malloc(sizeof(Node)); //creates a new node
if (newNode != NULL) //checks to make sure the node was allocated correctly
{
newNode->data = input; //makes the new node's data == input
newNode->nextPtr = NULL; //makes the nextPtr of the newNode NULL
}
currentPtr = newNode; //sets currentPtr to the address of the newNode
if(previousPtr == NULL) { //first time around previousPtr == NULL
newNode->nextPtr = newNode;
previousPtr = newNode; //sets previousPtr to the address of the new node (1st time only)
} else { //afterwards, currentPtr won't be NULL
previousPtr->nextPtr = currentPtr; //last node's pointer points to the current node
previousPtr = newNode; //update previous pointer to the current node
}
++counter;
//debug
printf("\nLoop #%d\n", counter);
}
revStart = reverse(newNode);
puts("The list is: ");
while (newNode != NULL){
printf("%c --> ", newNode->data);
currentPtr = currentPtr->nextPtr;
}
puts("NULL\n");
}
//reversing the nodes
Node* reverse(Node *stPtr)
{
//make a new node
NodePtr currentPtr = stPtr->nextPtr; //get the next letter ready (this will point to #2)
NodePtr prevRevPtr = NULL; //previous reverse node pointer
Node* revStart;
for(unsigned int counter = 1; counter <= 10; ++counter)
{
NodePtr revNode = malloc(sizeof(Node));
if(revNode != NULL) //if reverseNode is allocated...
{
if(prevRevPtr = NULL) //if previousReversePointer = NULL it's the "first" letter
{
revNode->data = stPtr->data; //letter = current letter
revNode->nextPtr = NULL; //this is the "last" letter, so NULL terminate
prevRevPtr = revNode; //previousReversePointer is this one
}else //after the first loop, the previous ReversePointer will be set
{
revNode->data = currentPtr->data; //set it's data to the pointer's data
revNode->nextPtr = prevRevPtr; //reverseNode's pointer points to last node entered
currentPtr = currentPtr->nextPtr; //moves to next letter
prevRevPtr = revNode; //changes previous reverse node to current node
if(counter == 10)//on the last loop...
{
revStart = revNode; //set revStart as a pointer to the last reverse node
//which is technically the "first"
}
}
}
}
return revStart;
}
Assuming your list is properly wired from inception, reversing a double-linked list is basically this:
Node *reverse(Node *stPtr)
{
Node *lst = stPtr, *cur = stPtr;
while (cur)
{
Node *tmp = cur->nextPtr;
cur->nextPtr = cur->prevPtr;
cur->prevPtr = tmp;
lst = cur;
cur = tmp;
}
return lst;
}
That's it . All this does is walk the list, swapping pointers, and retaining whatever the last node processed was. When done correctly the list will still be end-terminated (first node 'prev' is null, last node 'next' is null, and properly wired between.
I strongly advise walking a list enumeration through this function in a debugger. With each iteration watch what happens to cur as it marches down the list, to the active node's nextPtr and prevPtr values as their swapped, and to lst, which always retains the last-node processed. It's the new list head when done.
Okay so we don't need to contend with no line breaks in commments:
Node *reverse(Node *list) {
Node *rev = NULL;
while (list) {
Node *elt = list; // pop from the list
list = list->next;
elt->next = rev; // push onto reversed list.
rev = elt;
}
return rev;
}
As you wrote in comments, you probably don't need to have a previous pointer; you can just create a singly linked list.
There are several issues in your code, including:
When malloc returns NULL, you still continue with the loop -- only part of the code is protected by the if that follows, but not the rest. You should probably just exit the program when this happens.
Your algorithm does not maintain a reference to the very first node, i.e. the place where the linked list starts. When you print the list you should start with the first node of the list, but instead you start with newNode, which is the last node you created, so obviously not much will be printed except that last node. Moreover, both other pointers you have, will also point to the last node (currentPtr, previousPtr) when the loop ends.
newNode->nextPtr = newNode; temporarily creates an infinite cycle in your list. This is resolved in the next iteration of the loop, but it is unnecessary to ever make the list cyclic.
In the reverse function you have if(prevRevPtr = NULL)... You should get a warning about that, because that is an assignment, not a comparison.
Some other remarks:
The reverse function unnecessarily makes distinction between dealing with the first node and the other nodes.
It is also not nice that it expects the list to have 10 nodes. It would be better to just rely on the fact that the last node will have a NULL for its nextPtr.
It is a common habit to call the first node of a linked list, its head. So naming your variables like that is good practice.
As you are required to print both the initial list and the reversed list, it would be good to create a function that will print a list.
As you need to create new nodes both for the initial list and for the reversed list, it would be good to create a function that will create a node for you.
(I know that your teacher asked to create only one function, but this is just best practice. If this doesn't fit the assignment, then you'll have to go with the malloc-related code duplication, which is a pitty).
As you defined the type NodePtr, it is confusing to see a mix of Node* and NodePtr in your code.
Your question was first not clear on whether the reversal of the list should be in-place or should build a new list without tampering with the initial list. From comments it became clear you needed a new list.
I probably didn't cover all problems with the code. Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
struct charNode {
char data;
struct charNode *nextPtr;
};
typedef struct charNode Node;
typedef Node *NodePtr;
NodePtr reverse(Node *stPtr);
void printList(Node *headPtr);
NodePtr createNode(int data, NodePtr nextPtr);
int main(void) {
NodePtr headPtr = NULL; // You need a pointer to the very first node
NodePtr tailPtr = NULL; // Maybe a better name for currentPtr
printf("Enter 10 letters to make a list: ");
for (int counter = 0; counter < 10; counter++) {
char input;
scanf("%c", &input);
NodePtr newNode = createNode(input, NULL);
if (headPtr == NULL) {
headPtr = newNode;
} else {
tailPtr->nextPtr = newNode;
}
tailPtr = newNode;
}
NodePtr revHeadPtr = reverse(headPtr);
puts("The list is:\n");
printList(headPtr);
puts("The reversed list is:\n");
printList(revHeadPtr);
}
void printList(NodePtr headPtr) {
while (headPtr != NULL) {
printf("%c --> ", headPtr->data);
// You can just move the head pointer: it is a variable local to this function
headPtr = headPtr->nextPtr;
}
puts("NULL\n");
}
NodePtr createNode(int data, NodePtr nextPtr) {
NodePtr newNode = malloc(sizeof(Node));
if (newNode == NULL) { // If malloc fails, exit the program
puts("Cannot allocate memory\n");
exit(1);
}
newNode->data = data;
newNode->nextPtr = nextPtr;
return newNode;
}
NodePtr reverse(NodePtr headPtr) {
NodePtr revHeadPtr = NULL;
while (headPtr != NULL) {
revHeadPtr = createNode(headPtr->data, revHeadPtr);
// You can just move the head pointer: it is a variable local to this function
headPtr = headPtr->nextPtr;
}
return revHeadPtr;
}
I am a rookie programmer and I have a project which implies using binary trees. All I have to do is to insert a node, delete a node and add two methods of tree traversal. The issue is I can't get my code to work. I decided to add few helper functions such as check_element and create_NewNode to help me out implement easier. I don't get an output on my console after running or it simply greets me with a runtime error. I have got a header file, IO.c file to store my functions and the main.c.to test header file Implemented functions.
Here is IO.c , used to store the functions.
#include <stdio.h>
#include <stdlib.h>
#include "Library.h"
struct node{
int data;
struct node *left;
struct node *right;
};
struct node *root;
/*-----------------------------------------------------------------------------------------*/
//function to determine if an element is already in the tree
void check_element( struct node *node, int value)
{
while( node != NULL ){
//checking if the value is here
if( value == node->data ){
printf("The element %d already exists in the tree!",value);
exit(0);
//if the value is smaller, go left
}else if( value < node->data ){
check_element( node->left, value );
//else go right
}else if( value > node->data ){
check_element( node->right, value );
//else the element was not found and we can add it to th tree
}else{
printf("Adding the element %d to the tree.",value);
exit(0);
}
}//end while
}//end check_element
/*-----------------------------------------------------------------------------------------*/
//helper function to crate a new node and set left and right pointers to NULL
struct node *create_NewNode( int value )
{
struct node *ptr;
struct node *temp = (struct node*)malloc(sizeof(struct node));
ptr = (struct node*)malloc(sizeof(struct node));
if( ptr == NULL){
printf("Memory allocation error!");
exit(-1);
}
//assigning the data to the newly created node
temp->data = value;
//setting left and right pointers to NULL
temp->left = NULL;
temp->right = NULL;
return temp;
}
/*-----------------------------------------------------------------------------------------*/
//function to add a new value to the tree;
struct node *insert_value( struct node *node, int new_value )
{
//checking if the element already exists to the tree
check_element( node, new_value );
//checking if the tree is empty
if( node == NULL ){
node = create_NewNode( new_value );
//if the value is smaller, we add it to the left
}else if( new_value < node->data ){
insert_value( node->left, new_value );
//else we add it to the right
}else{
insert_value( node->right, new_value );
}
return node;
}
/*-----------------------------------------------------------------------------------------*/
void printPostorder( struct node *node )
{
if (node == NULL){
printf("The tree is empty!");
exit(0);
}else{
//first go left
printPostorder( node->left );
//then go right
printPostorder( node->right );
//finally, print the node value
printf("%d", node->data);
}
}
/*-----------------------------------------------------------------------------------------*/
void inorder_traversal( struct node *node )
{
if( node == NULL) {
printf("The tree is empty!");
exit(0);
}else{
//first go left
inorder_traversal( node->left );
//print the node value
printf("%d ",node->data);
//then go right
inorder_traversal( node->right );
}
}
/*-----------------------------------------------------------------------------------------*/
This is the header file, called Library.h
//prototype for NewNode
struct node *create_NewNode( int value );
//prototype for insert_value
struct node *insert_value( struct node *node, int new_value );
//prototype for printPostordre
void printPostorder( struct node* node);
//prototype for printInorder
void inorder_traversal( struct node *node );
//prototype for check_element
void check_element( struct node *node, int value);
And, finally, the main.c: `enter code here:
#include <stdio.h>
#include <stdlib.h>
#include "Library.h"
int main()
{
// TEST CODE
struct node *root;
root = NULL;
insert_value(root, 1);
insert_value(root, 2);
insert_value(root, 3);
printPostorder( root );
inorder_traversal( root );
return 0;
}
PS: I did my best to write this code, but, as I said, I am a rookie and I'm pretty bad at coding.I'd also like to appologize for any grammar mistakes, i am not an englishman.
There may be more mistakes, but I read the create_node() and want to advice on it:
struct node *create_NewNode( int value )
{
struct node *ptr;
struct node *temp = malloc(sizeof(struct node));
ptr = malloc(sizeof(struct node));
if( ptr == NULL){
printf("Memory allocation error!");
exit(-1);
}
//assigning the data to the newly created node
temp->data = value;
//setting left and right pointers to NULL
temp->left = NULL;
temp->right = NULL;
return temp;
}
Here you are creating two nodes, while you intend to create only one. You treat temp as the new one, while you forget about ptr. You don't need to create another node!
What you need is the pointer of the tree, so that you add the newly constructed node at that tree (thus you could pass another parameter to that function, tree's pointer).
BTW, I removed the casts of malloc, as explained in Do I cast the result of malloc?
I suggest trying to fix your code after my advice. However, I will link you to treemanagement.c, which is c code for a tree, fully commented, and it's the way I learned about this data structure, it might can in handy in the future!
I forgot about this post. I have got it to work. This is what I used:
For the header file:
///\file Header.h
///\brief The header containing all the prototypes for our functions.
struct node *Create_node( int value );
void delete_value(struct node **root, int val_del) ;
void inorder_traversal( struct node *node );
void insert_value( struct node **head, int new_value );
void pre_order_traversal( struct node* node );
struct node* search_by_value(struct node* node, int value);
int random_value_generator(int domain);
For the implementation of the functions:
///\file Functions.c
///\brief C library implementation for BST.
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"
//In this structure we'll be storing our BST.
struct node{
///\struct struct node
///\brief It represents our structure to store our BST.
int data;
struct node *left;
struct node *right;
};
/*-----------------------------------------------------------------------------------------------------*/
/*
Helper function which creates a new node, containing the desired value and setting left and right
pointers to NULL.
*/
struct node *Create_node( int value )
{
///\fn struct node *Create_node(int value)
///\brief Returns a new node, initialised with "value" and 2 NULL pointers, left and right.
///\param value The value which we want to initiliase the newly created node with.
//Creating the new Node and allocating memory to it.
struct node *new_node = (struct node*)malloc(sizeof(struct node));
//Assigning the desired value to the newly created node.
new_node->data = value;
//Setting left and right pointers to NULL;
new_node->left = NULL;
new_node->right = NULL;
return new_node;
};
/*-----------------------------------------------------------------------------------------------------*/
/*
The first traversal method.
*/
void pre_order_traversal( struct node* node )
{
///\fn pre_order_traversal(struct node* node)
///\brief A function used to 'traverse' the tree. It actually is a printing function.
///\param node It represents the starting point of printing.
//Checking if the tree is not empty.
if( node != NULL ) {
///It will print the root, then the left child, then the right child.
//Printing the node.
printf( "%d ",node->data );
//Printing the left child.
pre_order_traversal( node->left );
//Printing the right child.
pre_order_traversal( node->right );
}
}
/*-----------------------------------------------------------------------------------------------------*/
/*
A function which inserts a new node in the tree.
*/
void insert_value( struct node **head, int new_value )
{
///\fn insert_value(struct node **head, int new_value)
///\brief Inserts a new node into our BST.
///\param head This parameter is passed as a double pointer to avoid any conflicts with other fucntions.
/// and represents the starting point of insertion. The function will start searching for the appropriate
/// position to insert the value.
///\param new_value Is the new value which will be assigned to the new node;
//Initialising the pointer.
struct node *current = *head;
//Checking if the the current node is NULL, if it is, we create a new node.
if( current == NULL){
//If the root is NULL, then we create a new new node, containing the new value.
current = Create_node( new_value );
*head = current;
}else{
//Else, if the value is smaller, recur to the left.
if( new_value < current->data ){
insert_value( ¤t->left, new_value );
}else{
//Else recur to the right.
insert_value( ¤t->right, new_value );
}
}
}
/*-----------------------------------------------------------------------------------------------------*/
/*
The second traversal method.
*/
void inorder_traversal( struct node *node )
{
///\fn inorder_traversal(struct node* node)
///\brief A function used to 'traverse' the tree. It actually is the second printing function.
///\param node It represents the starting point of printing.
if( node != NULL ) {
///It will print the left child, then the root, then the right child.
//Printing the left child.
inorder_traversal( node->left );
//Printing the root.
printf( "%d ",node->data );
//Printing the right child.
inorder_traversal( node->right );
}
}
/*-----------------------------------------------------------------------------------------------------*/
/*
A function which deletes a node.
*/
void delete_value(struct node **root, int val_del)
{
///\fn void delete_value(struct node **root, int val_del)
///\brief It is the most complex function and it is used to delete a node.
/// There are multiple cases of deletion, such as: a leaf node (a node without any children),
/// a node with a child on the right, a node with a child on the left or a node with 2 children.
//We are starting from root, with two pointers: current and parent.
struct node *current = *root;
struct node *parent;
//We recur on the tree untill we find the node containing the value which we want to remove.
while (current->data != val_del) {
//Moving the parent to root. The root's parent is NULL. (root has no parent)
parent = current;
//If the value is greater the parent's value, recur right.
if (current->data > val_del) {
current = current->left;
}else{
//Else recur left.
current = current->right;
}
}
//Checking if the node is a leaf node. (no children on the left or right)
if ((current->left == NULL) && (current->right == NULL)) {
//Comparing the node's value with the value of its parent.
//If the value is smaller, we remove the left children.
if (current->data < parent->data) {
parent->left = NULL;
}else{
//Else we remove the right child.
parent->right = NULL;
}
free(current);
//Else, we check if it has a child on the left.
}else if (current->right == NULL) {
//Checking if our node is the root.
if(current == *root) {
//Using an aux to free the root, so the memory is not allocated to it anymore .
struct node *aux;
aux = (*root)->left;
free(*root);
(*root) = aux;
//If the node is not the root, we proceed.
}else{
//If the node's parent value is greater the the value of our node. If true, we replace
//the parent's left child with its left succesor and remove (free) the node.
if (current->data < parent->data) {
parent->left = current->left;
free(current);
}else{
//Else, we do the same thing, but for the parent's right child.
parent->right = current->left;
free(current);
}
}
//Else, we check if it has a child on the right.
}else if(current->left == NULL) {
//Checking if our node is the root.
if(current == *root) {
//Using an aux to free the root, so the memory is not allocated to it anymore.
struct node *aux;
aux = (*root)->right;
free(*root);
*root = aux;
//If the node is not the root, we proceed.
}else {
if (current->data < parent->data){
//If the node's parent value is smaller the the value of our node. If true, we replace
//the parent's left child with its right succesor and remove (free) the node.
//It is the mirrored code of the previous case.
parent->left = current->right;
free(current);
}else{
//Else, we do the same thing, but for the parent's right child.
parent->right = current->right;
free(current);
}
}
//Else, the node has 2 children. This is the last case.
}else if( (current->right != NULL) && (current->left != NULL)){
//In order to replace the root, we need to go one step to the right,
//and then all the way to the left, retrieve the smallest value,
//which will replace the root.
struct node *temp = current->right;
int aux;
while (temp->left != NULL) {
temp = temp->left;
}
//This si where we do the swap.
aux = temp->data;
current->data = aux;
temp = temp->right;
}
}
/*-----------------------------------------------------------------------------------------------------*/
/*
Helper function to determine if a value already exists in the tree.
*/
struct node* search_by_value(struct node* node, int value)
{
///\fn struct node* search_by_value(struct node* node, int value)
///\brief It is a function used to check if an element already exists in the tree.
/// If the fucntion returns NULL, it means that the element DOESN'T belong to the tree.
//Checking if the current node is empty or it has the value which we are looking for.
if (node == NULL || node->data == value){
return node;
free(node);
}
//If the value is greater, recur right.
if( value > node->data ){
return search_by_value(node->right, value);
}else{
//Else recur left.
return search_by_value(node->left, value);
}
//Returning NULL if the element wasn't found.
return NULL;
}
/*-----------------------------------------------------------------------------------------------------*/
/*
A simple function to generate random numbers,
between 0 and a domain.
*/
int random_value_generator(int domain)
{
///\fn int random_value_generator(int domain)
///\brief It generates random numbers between 0 and a set domain.
///\param domain It represents the dmain.(the upper boundry for our generation)
return rand()%domain;
}
And finally the the main file:
///\file main.c
///\brief The driver program for our BST library, containing a command line.
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"
//Setting the root to NULL.(empty tree)
struct node *root=NULL;
int main()
{
//Preparing the command line. The choice is like a task selector.
int choice;
//Infinitely recuring until the user decides to exit or there is an error.
do{
//Printing the command line and acquiring the choice.
printf("\nWhat would you like to do ? Select:");
printf("\n1-Add value;\n2-Delete value;\n3-Print In-Order;\n4-Print Pre-Order;\n5-Random;\n6-Exit;");
printf("\n");
printf("\nYour choice:");
scanf("%d",&choice);
switch(choice){
//The first case is used for insertion of a new value.
case 1:{
//Initialising the local values.
int iterations=0,number=0,value=0,iterator=0;
//Setting up a pointer, for later use.
struct node *ptr;
//Acquiring the number of iterations.
printf("\nHow many values would you like to insert? Type a value:");
scanf("%d",&iterations);
//Inserting values as many times as we initiliased "iterations".
while( number < iterations ){
printf("\nValue[%d]=",iterator);
scanf("%d",&value);
//Using the pointer to check if the value already exists.
ptr = search_by_value( root, value );
if( ptr == NULL ){
//In case of ptr = NULL, we add it to the BST.
insert_value(&root,value);
value = 0;
}else{
//Else we ask for another value, without affectig the number of iterations.
printf("\nThe element %d already exists in the tree!",value);
//Resetting the pointer and the vaue to be reused.
value = 0;
ptr = NULL;
//A simple way to keep the loop consistent.
//If we want to insert 10 values and 1 would already exists,
//we would only have 9 values. This way, even if there a values
//already exists, we will still have to insert the appropriate
//nuber of values.
number--;
iterator--;
}
//Incrementing the iterators to prevent an ifinite loop.
number++;
iterator++;
}
//Reseting the iterator to be used later.
iterator=0;
break;
};//end case-1
//The second case is used for deletion.
case 2:{
//Initialising the value.
int d_value=0;
//Acquiering the value we want to delete.
printf("\nWhich value would you like to delete? \nType a value:");
scanf("%d",&d_value);
//Checking if the value exists in the tree.
struct node *ptr = search_by_value( root, d_value );
if( ptr != NULL ){
//If ptr != NULL, it means that the value exists in the tree
// and it can be deleted.
printf("\nDeleting %d !",d_value);
//Deleting the value.
delete_value(&root, d_value);
//Reseting the value for laer use
d_value = 0;
}else if( ptr == NULL ){
//Else the value does not belong to the tree, so it cannot be deleted.
printf("\nThe element %d doesn't belong to the tree!",d_value);
printf("\n");
//Resetting the pointer and the value for later use.
d_value = 0;
ptr = NULL;
}else{
//Else our tree is empty.
printf("\nEmpty Tree!");
}
break;
};//end case-2
//The third case is used for in-order traversal.
case 3:{
printf("\nIn-order traversal:");
inorder_traversal(root);
printf("\n");
break;
};//end case-3
//The fourth case is used for pre-order traversal.
case 4:{
printf("\nPre-order traversal:");
pre_order_traversal(root);
printf("\n");
break;
};//end case-4
//The fifth case is used for randomly inserting value into teh BST.
case 5:{
//Initialising the values.
int iterations=0,number=0,value=0,iterator=0,domain=0;
//Setting up a pointer for later use.
struct node *ptr;
//Acquiering the number of iterations.
printf("\nHow many values would you like to insert? Type a value:");
scanf("%d",&iterations);
//Acquiering the domain for the random generator.
printf("\nPlease type the domain for the randomly generated numbers.");
printf("\nPlease type a value:");
scanf("%d",&domain);
//Iterating until all the values have been successfully inserted.
while( number < iterations ){
//The new value to be inserted is generated using our fucntion.
value = random_value_generator(domain);
//Checking if the values already exists in the tree.
ptr = search_by_value( root, value );
if( ptr == NULL ){
printf("\nInserting %d!",value);
//If ptr = NULL, we can safely insert the value into our BST.
insert_value(&root,value);
//Resetting the value for later use.
value = 0;
}else{
//Else, we cannot insert the value, as it already exists.
printf("\nThe element %d already exists in the tree!",value);
//Resetting the pointer and the value.
value = 0;
ptr = NULL;
//Same trick to insert the exact number of values.
number--;
iterator--;
}
//Incrementing to prevent infinite looping.
number++;
iterator++;
}
//Resetting the iterator for later use.
iterator=0;
break;
};//end case-5
//The sixth case is used to exit the proram at will.
case 6:{
exit(0);
};//end case-6
//The default case occurs in case of error. (hope not)
default :{
printf("\nError!");
exit(-1);
};//end default
}//end switch
}while(1);//end while
return 0;
}
I used double pointers and that got rid of my problems. I hope this will help someone.
Write a function AlternatingSplit() that takes one list and divides up its nodes to make two smaller lists ‘a’ and ‘b’. The sublists should be made from alternating elements in the original list. So if the original list is 0->1->0->1->0->1 then one sublist should be 0->0->0 and the other should be 1->1->1.
More details about the problem - http://www.geeksforgeeks.org/alternating-split-of-a-given-singly-linked-list/
Now i made this code and it's running successfully
#include<stdio.h>
#include<stdlib.h>
struct node
{
int num;
node *next;
};
node *start1 = NULL, *start2 = NULL, *start3 = NULL;
void push()
{
node *temp = (node *)malloc(sizeof(node));
printf("Enter number = ");
scanf("%d", &temp->num);
temp -> next = start1;
start1 = temp;
}
void split()
{
while(start1 != NULL)
{
node *temp1 = (node *)malloc(sizeof(node));
temp1 ->num = start1 ->num;
temp1->next = start2;
start2 = temp1;
start1 = start1 -> next;
if(start1 != NULL)
{
node *temp2 = (node *)malloc(sizeof(node));
temp2 ->num = start1 ->num;
temp2->next = start3;
start3 = temp2;
start1 = start1 -> next;
}
}
}
int main()
{
int n;
scanf("%d", &n);
while(n--)
push();
split();
node *temp = start2;
while(temp != NULL)
{
printf("%d ", temp ->num);
temp = temp ->next;
}
printf("\n");
temp = start3;
while(temp != NULL)
{
printf("%d ", temp ->num);
temp = temp ->next;
}
return 0;
}
And the code provided with the question is -
/*Program to alternatively split a linked list into two halves */
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
/* Link list node */
struct node
{
int data;
struct node* next;
};
/* pull off the front node of the source and put it in dest */
void MoveNode(struct node** destRef, struct node** sourceRef) ;
/* Given the source list, split its nodes into two shorter lists.
If we number the elements 0, 1, 2, ... then all the even elements
should go in the first list, and all the odd elements in the second.
The elements in the new lists may be in any order. */
void AlternatingSplit(struct node* source, struct node** aRef, struct node** bRef)
{
/* split the nodes of source to these 'a' and 'b' lists */
struct node* a = NULL;
struct node* b = NULL;
struct node* current = source;
while (current != NULL)
{
MoveNode(&a, ¤t); /* Move a node to list 'a' */
if (current != NULL)
{
MoveNode(&b, ¤t); /* Move a node to list 'b' */
}
}
*aRef = a;
*bRef = b;
}
/* Take the node from the front of the source, and move it to the front of the dest.
It is an error to call this with the source list empty.
Before calling MoveNode():
source == {1, 2, 3}
dest == {1, 2, 3}
Affter calling MoveNode():
source == {2, 3}
dest == {1, 1, 2, 3}
*/
void MoveNode(struct node** destRef, struct node** sourceRef)
{
/* the front source node */
struct node* newNode = *sourceRef;
assert(newNode != NULL);
/* Advance the source pointer */
*sourceRef = newNode->next;
/* Link the old dest off the new node */
newNode->next = *destRef;
/* Move dest to point to the new node */
*destRef = newNode;
}
/* UTILITY FUNCTIONS */
/* Function to insert a node at the beginging of the linked list */
void push(struct node** head_ref, int new_data)
{
/* allocate node */
struct node* new_node = (struct node*) malloc(sizeof(struct node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* Function to print nodes in a given linked list */
void printList(struct node *node)
{
while(node!=NULL)
{
printf("%d ", node->data);
node = node->next;
}
}
/* Drier program to test above functions*/
int main()
{
/* Start with the empty list */
struct node* head = NULL;
struct node* a = NULL;
struct node* b = NULL;
/* Let us create a sorted linked list to test the functions
Created linked list will be 0->1->2->3->4->5 */
push(&head, 5);
push(&head, 4);
push(&head, 3);
push(&head, 2);
push(&head, 1);
push(&head, 0);
printf("\n Original linked List: ");
printList(head);
/* Remove duplicates from linked list */
AlternatingSplit(head, &a, &b);
printf("\n Resultant Linked List 'a' ");
printList(a);
printf("\n Resultant Linked List 'b' ");
printList(b);
getchar();
return 0;
}
My query here is, which of these two codes are more efficient and more correct for this question, considering the time complexity, space complexity and every other factor?
And why?
A detailed explanation will be more helpful.
When you just split a linked list, you don't need any memory allocations, it's enough to just shuffle around pointers.
Your code does memory allocations when splitting, so it is rather inefficient that way, the model answer code is much better.
But worse, your code leaks memory. It loses the pointers to original list elements without freeing them. So your code is actually buggy, in a bad way.
To fix just the memory leak, which is an actual bug, you would need to change the two start1 = start1 -> next; lines to this:
node *tmp_next = start1->next;
free(start1);
start1 = tmp_next;
For other changes, the model answer is a good example, but most important things would be: Get rid of the extra malloc calls, and do the split by moving nodes, instead of allocating new node and copying data (and, after above bugfix, freeing the old node). And then get rid of the global variables, instead add parameters to the functions, like in the model answer.
Just another quick split, no new allocations, and keeping the original list reduced to odd elements, while forming the new lists for even ones, along with comment on each critical step
void split_in_evenodd(node *orig)
{
if(!orig)
return;
node *e, *cur, *e_hd;
e = orig->next; // point first even member
e_hd = e; // keep a head pointer to even list
if(!e) // covers the case of list with single element
return;
orig->next = e->next; // make orig skip the even node
cur = orig->next; // cur moves to next odd node
while(cur && cur->next) {
e->next = cur->next; // even pointing to next even node
e = e->next; // move even list forward
cur->next = e->next; // update odds next
cur = e->next;// move current forward (to next odd)
}
}
While solving this problem, I came up with this approach where I have created separate head nodes for both the splits and then with the help of count variable, all odd count linked list nodes are sent to split linked list 1 and all even count linked list nodes are sent to split linked list 2.
Hope it helps! This code is in C language.
#include <stdio.h>
#include <stdlib.h>
struct node *add_at_end(struct node *ptr,int item);
struct node{
int data;
struct node *next;
};
void main(){
struct node *head=malloc(sizeof(struct node));
head->data=1;
head->next=NULL;
// first node gets created
struct node *ptr=head;
//now we will add other nodes at the end
ptr=add_at_end(ptr,2);
ptr=add_at_end(ptr,3);
ptr=add_at_end(ptr,4);
ptr=add_at_end(ptr,5);
//the nodes get added to the linked list.Now let's print the data of all these nodes
ptr=head;
while(ptr!=NULL){
printf("%d ",ptr->data);
ptr=ptr->next;
}
printf("\n");
int count;
struct node *splitNode=malloc(sizeof(struct node));
struct node *forward=malloc(sizeof(struct node));
forward=head;
//now we will create the 1st split linked list
struct node *headll1=malloc(sizeof(struct node));
splitNode=forward;
forward=forward->next;
headll1->data=splitNode->data;
headll1->next=NULL;
struct node *ptr1=headll1;
count=1;
//now we will create the 2nd split linked list
struct node *headll2=malloc(sizeof(struct node));
splitNode=forward;
forward=forward->next;
headll2->data=splitNode->data;
headll2->next=NULL;
struct node *ptr2=headll2;
count++;
//head nodes of both the split linked lists is ready
while(forward!=NULL){
splitNode=forward;
forward=forward->next;
count+=1;
if(count%2==1){
ptr1->next=splitNode;
splitNode->next=NULL;
ptr1=ptr1->next;
}else{
ptr2->next=splitNode;
splitNode->next=NULL;
ptr2=ptr2->next;
}
}
//we have finished adding the nodes to linked list 1 and 2 alternatively based on count.
//now let's print both the linked lists.
ptr1=headll1;
while(ptr1!=NULL){
printf("%d ",ptr1->data);
ptr1=ptr1->next;
}
printf("\n");
ptr2=headll2;
while(ptr2!=NULL){
printf("%d ",ptr2->data);
ptr2=ptr2->next;
}
}
struct node *add_at_end(struct node *ptr,int item){
struct node *temp=malloc(sizeof(struct node));
temp->data=item;
ptr->next=temp;
temp->next=NULL;
return temp;
}
EDIT: Figured out the problem. Also if you found this through google or another search engine here is where I went wrong and how to fix it.
My deleteNode() method was moving through the list properly with the correct temp and keeping the head untouched. Where I was going wrong was in what I was returning as the result of the method. I was returning either temp or newNode which is incorrect because it goes through the list until it finds defined position. Once it finds that defined position it it would reassign the ->next pointer to point to the next->next> pointer which is correct but again I was returning the wrong thing. Because we had moved through the list using temp/NewNode we lost the header and we were returning the position we found and whatever was still in the next positions of the list.
How we fix this is returning the head (which is what is passed into the method). The reason why this works is because we have to understand how LinkedLists work. The pointers of each node point to the next node. Ex. we have a linked list |A|| - |B|| - |C|| - |D|| - |E|| - |F||
If we want to delete Node C we move to node B using the temp pointer and then assign the B->next to temp->next->next Thus skipping over C node and assigning D node.
NOTE: (From what I know this does not actually free the memory of C node so it isn't best practice because you can cause memory leaks this way) You should use the free() method on the C node.
Here is the code I ended up using
struct node* DeleteNode(struct node* head, int pos) {
struct node* temp = head;
int length = LinkedListLength(temp);
int i;
if(pos <= 0 || pos > length){
printf("ERROR: Node does not exist!\n");
}else{
if(pos == 1){
head = head->next; //move from head (1st node) to second node
}else{
for(i = 1; i < pos-1; ++i){ //move through list
temp = temp->next;
}
temp->next = temp->next->next;
}
}
return head;
}
Hopefully that helps understand how I went out fixing it.
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
ORIGINAL POST
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
EDIT: Note: This is a homework assignment I have spent a few days (estimated 4 hours) programming it I am just stuck on this one part. You can view my attempt below
I've been able to insert and delete from begining/end however I can't seem to get my delete node at position N in linkedlist to work.
My psuedocode looks like this:
LinkedList: 1,3,5,7,9,23
Grab LinkedList
Create new struct node A = head
Move through linkedlist until
position
Assign node to node->next
return linkedlist
EXAMPLE INPUT
Node structure
int data;
struct node* next;
int values[] = {1,3,5,7,9,23};
struct node* llist = CreateList(values,6);
llist = DeleteNode(llist, 1);
llist = DeleteNode(llist, 5);
llist = DeleteNode(llist, 3);
Which should leave the llist with the values 3, 5, 9 once the code has been run However, It is replacing the first node with a 0
Actual Code:
struct node* DeleteNode(struct node* head, int pos) {
struct node* temp = head;
struct node* newNode = head;
int length;
int i;
printf("DeleteNode: position = %d \nBefore: ", pos);
PrintList(temp);
if(pos <= 0){ //node does NOT exist
printf("ERROR: Node does not exist!\n");
}else{ //node DOES exist
length = LinkedListLength(temp);
if(length < pos){ //if length < position Node does not exist
printf("ERROR: Node does not exist!\n");
}else{
if(pos == 0){
newNode = temp->next;
}else if(pos == 1){
newNode = temp->next;
}else{
for(i = 1; i < pos; i++){
printf("i = %d\n", i);
temp = temp->next;
newNode->next;
}
if(temp->next == NULL){
newNode = NULL;
}else{
newNode = temp->next;
}
}
printf("After: ");
PrintList(newNode);
printf("\n");
}
}
return newNode;
}
EDIT #2: Code typo
Thanks for any help in advance. From what I have concluded my problem is that I am not moving through the list properly but I am unsure as to why I am not.
In your code, you have the line
newNode->next;
in your for loop. That operation doesn't do anything.
You also have
newNode-> = NULL;
which is not valid C, and I have no idea how you got that to compile.
But really, don't use that loop. A linked list is one of the most basic recursive data structures. As a result, almost all algorithms manipulating them are most elegant as a recursive solution.
typedef struct node node_t;
node_t* delete_at_index(node_t* head, unsigned i)
{
node_t* next;
if(head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next) /* If i == 0, the first element needs to die. Do it. */
: (head->next = delete_at_index(next, i - 1), head); /* If it isn't the first element, we recursively check the rest. */
}
Removing a given node n from a singly-linked list can be boiled down to this operation:
Set the pointer that points to n to point instead to n->next.
You can break this down into two operations:
Find the pointer that points to n;
Set that pointer to n->next.
The complication arises because the pointer that points to n might either be the p->next field of the previous node in the list, or the head pointer (if n is the first node in the list).
Your code does not appear to be complete - it doesn't ever set the ->next field of any node to anything, so it's hard to say what's actually wrong.
// Remove list's node located at specified position.
// Arguments:
// head -- list's head
// pos -- index of a node to be removed (1-based!!!)
struct node* DeleteNode(struct node* head, int pos)
{
struct node* node;
struct node* prev;
int length;
int i;
printf("DeleteNode: position = %d \nBefore: ", pos);
PrintList(head);
// Check position's lower bound. Should be >= 1
if(pos <= 0) { //node does NOT exist
printf("ERROR: Node does not exist!\n");
return head;
}
// Seek to the specified node, and keep track of previous node.
// We need previous node to remove specified node from the list.
for(i=1, prev = 0, node = head; i < pos && node != 0; i++) {
prev = node;
node = node->next;
}
// Out of range
if(0 == node) {
printf("ERROR: Index out of bounds!\n");
return head;
}
// #node points to a list's node located at index pos
// #prev points to a previous node.
// Remove current node from the list.
if(0 == prev) {
head = node->next;
}
else {
prev->next = node->next;
}
free(node);
return head;
}
Your DeleteNode doesn't delete a node, it removes pos nodes from the front of the list. So you're trying to remove 9 items from a list that only contains 6, resulting of course in an empty list (NULL). Also, your code is overly complex and contains remnants of previous attempts. Please don't do that to yourself or to us; provide simple clean code and it will be easier to understand and to fix.
Figured out your for loop isn't reaching the desired position you wanted.
Better use equal to sign for the constraint it will work.
e.g.
for (i=1;i<=position-1;i++)
{
}