Linked list in C – search method - c

As at the last time, suppose we have doubly linked list of nodes
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node* next;
struct Node* prev;
} Node;
typedef struct LinkedList {
Node *first;
Node *last;
} LinkedList;
void initList(LinkedList* l) {
l->first = NULL;
l->last = NULL;
}
and my task is to code search method, which should find a node with given value
Node* search(LinkedList *list, int value) { ... }
well, my attempt follows
Node* search(LinkedList *list, int value) {
Node *node = malloc(sizeof(Node));
if (node == NULL)
return NULL;
node->value = value;
node->prev = NULL;
node->next = list->first;
while((node->value != value) && (node->next != NULL)){
node->prev = node->next;
node->next = (node->next)->next;
}
return node;
}
according to the implemenatation tests (this is not my job :-)
void test_search_exist() {
printf("Test 3: ");
LinkedList l;
initList(&l);
Node n1, n2;
n1.value = 1;
n1.next = &n2;
n1.prev = NULL;
n2.value = 2;
n2.next = NULL;
n2.prev = &n1;
l.first = &n1;
l.last = &n2;
Node *i = search(&l, 2);
if (i == &n2) {
printf("OK\n");
}else{
printf("FAIL\n");
}
}
void test_search_not_exist(){
printf("Test 4: ");
LinkedList l;
initList(&l);
Node n1, n2;
n1.value = 1;
n1.next = &n2;
n1.prev = NULL;
n2.value = 2;
n2.next = NULL;
n2.prev = &n1;
l.first = &n1;
l.last = &n2;
Node *i = search(&l, 3);
if (i == NULL) {
printf("OK\n");
}else{
printf("FAIL\n");
}
}
my code breaks either for existing or non-existing nodes. So is there any logic mistake or whatever?

Firstly: Dont allocate within search. The data members already exist, since you created them ahead.
Secondly: Iterate through the list and check every node for it's value.
Node* search(LinkedList *list, int value)
{
Node *node = list->first;
Node *found = NULL;
while(node != NULL)
{
if(node->value == value)
{
found = node;
break;
}
node = node->next;
}
return found;
}
To be more specific with the error(s) you made:
You allocated a node then filled it with the pointers of the first node, but with the value you were searching for. Then you started to loop over the list with the condition to stop when node->value equals the value you were searching for. Since node->value was initialized with the value your were searching for, this comparison will always be false (since its the same), the loop will be terminated and you get a bad result.
Besides this, your original code would result in a memory leak, since you malloc a new node, but you dont free it.

Related

variable "tmp" used in loop condition not modified in loop body

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node* next;
}
node;
int main(void){
node* list = NULL;
node *n = malloc(sizeof(node));
if(n==NULL){
return 1;
}
n->number = 2;
n-> next = NULL;
list = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list);
return 1;
}
n->number = 3;
n->next = NULL;
list->next = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list->next);
free(list);
}
n->number = 4;
n->next = NULL;
list->next->next =n;
n = malloc(sizeof(node));
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
for( node* tmp = list; tmp != NULL; tmp->next){
printf("%i\n" , tmp->number);
}
while(list!=NULL){
node*tmp = list->next;
free(list);
list=tmp;
}
}
was trying linked list.
expected when running the code:
0
1
2
3
4
$
//asdoihasidashiofdhiohdfgdiwheifiopioioiophfaifjasklfhafiashfauiosfhwuiohwefuiowhfaslfidasdaskdasjdlaksdjqwfiqpweiojfkldfjsdfklwhefiowefweopfiosfkosid;fjwdfp;fdasiopfjew[0fowejfwepfojmofejmiwrfgj;wdfjewio;fijwefjsdp;jfkl;wjw
Actually you are not changing the pointer
for( node* tmp = list; tmp != NULL; tmp->next){
You need to write
for( node* tmp = list; tmp != NULL; tmp = tmp->next){
It will be even better to write
for ( const node* tmp = list; tmp != NULL; tmp = tmp->next ){
because within the loop the list is not being changed.
Also in this code snippet
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
the statement
n->next = NULL;
is redundant.
In this loop, tmp->next has no effect because you don't assign it to anything.
for (node* tmp = list; tmp != NULL; tmp->next) {
printf("%i\n", tmp->number);
}
You must do tmp = tmp->next:
for (node* tmp = list; tmp != NULL; tmp = tmp->next) {
// ^^^^^
printf("%i\n", tmp->number);
}
Also, you can't expect 1 to be in the output because you never create a node with that number. With the above change the program will therefore output:
0
2
3
4
Sidenote: Your program is full of repetition which makes it hard to find errors and it's also what makes it harder to see that you forgot to add the node with the number 1. If you instead make functions of the things that you do repeatedly it'll be much clearer. You can also make functions with descriptive names to make the whole program easier to read and maintain.
If your program was rewritten to make use of functions, it could look like below - and then it'll be very obvious that the node with the number 1 is missing.
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node {
int number;
node* next;
};
node *create_node(int number, node *next) {
node *nn = malloc(sizeof *nn);
if(!nn) exit(1);
// assign values to the new node:
*nn = (node){.number = number,
.next = next};
return nn;
}
void insert_first(node **list, int number) {
*list = create_node(number, *list);
}
void insert_last(node **list, int number) {
// find the last "next" pointer (the one pointing at NULL):
while(*list) list = &(*list)->next;
// make the pointer pointing at NULL now point at the new node:
*list = create_node(number, NULL);
}
void free_all(node **list) {
for(node *tmp; *list; *list = tmp) {
tmp = (*list)->next;
free(*list);
}
}
void print_all(const node *list) {
for (; list; list = list->next) {
printf("%d\n", list->number);
}
}
int main(void) {
node* list = NULL;
insert_last(&list, 2);
insert_last(&list, 3);
insert_last(&list, 4);
insert_first(&list, 0);
print_all(list);
free_all(&list); // list == NULL after this
}

unable to insert into ordered linked list in C

i am new to programming and C. I am trying to create an ordered linked list. For some reason which i cannot figure out, it never enters the first if block in the insert_in_order function even though my linked list is empty when i call the insert_in_order function. Would anyone have any idea what i am doing wrong?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
struct node {
int value;
struct node* next;
};
typedef struct node node_t;
void printlist(node_t *head){
node_t *temporary = head;
while(temporary != NULL){
printf("%d - ", temporary->value);
temporary = temporary->next;
}
printf("\n");
}
node_t *create_new_node(int value){
node_t *result = malloc(sizeof(node_t));
result->value = value;
result->next = NULL;
//printf("result.value = %d\n", result->value);
return result;
}
void insert_in_order (node_t *head, node_t *node_to_insert){
node_t *current_node = head;
node_t *prior_node = head;
//linked list is empty
if (head == NULL){ //never enters if block for some reason
head->next = node_to_insert;
node_to_insert->next = NULL;
break;
//printf("inside the if stmt");
}
if(node_to_insert->value <= current_node->value){
head->next = node_to_insert;
node_to_insert->next = current_node;
break;
}
current_node = current_node->next;
while (current_node->next != NULL){
if(node_to_insert->value <= current_node->value){
node_to_insert->next = current_node;
prior_node->next = node_to_insert;
break;
}
else if (node_to_insert > current_node){
current_node = current_node->next;
prior_node = prior_node->next;
}
}
//node to insert is the largest in the linked list
current_node->next = node_to_insert;
node_to_insert->next = NULL;
}
int main(){
node_t *head;
node_t *node1;
node_t *node2;
head = NULL;
node1 = create_new_node(22);
node2 = create_new_node(33);
printf("node1's value equals %d\n", node1->value);
printf("node2's value equals %d\n", node2->value);
insert_in_order(head, node1);
printlist(head);
}
First of all this code does not compile - these breaks are invalid
if (head == NULL){ //never enters if block for some reason
head->next = node_to_insert;
node_to_insert->next = NULL;
break; <<<<====
//printf("inside the if stmt");
}
and
if (node_to_insert->value <= current_node->value) {
head->next = node_to_insert;
node_to_insert->next = current_node;
break; <<<=====
}
Seems like you meant return when you said break, now compiles with those replaced by return
Now this goes wrong
//linked list is empty
if (head == NULL) { //never enters if block for some reason
head->next = node_to_insert;
You just tested to see if head is NULL and if it is you try to use it, thats never going to work
You mean this
//linked list is empty
if (head == NULL) { //never enters if block for some reason
head = node_to_insert;
node_to_insert->next = NULL;
return;
}
code now runs to completion, although there may be other errors
node1's value equals 22
node2's value equals 33

Inserting elements in a linked list in various indices using one function only

This is the code I tried writing down to add an element in a double linked list, that takes an index and a value and adds a new element to the original list.
It is taking index and value but just adds the elements I give like a stack.
node *add(node *head, int index, int val)
{
node *new = create(val);
node *temp = malloc(sizeof(node));
if (head == NULL)
{
head = new;
temp = head;
//printf(": %d",temp->data);
}
temp = head;
int i = 1;
while (i < (index - 1) && (temp->next != NULL))
{
i++;
temp = temp->next;
}
temp->next = new;
new->next = NULL;
new->prev = temp;
return head;
}
however this code(for a doubly linked list) just adds elements one after the other, disregarding the index passed.
My prof gave us a code for a singly linked list where he did something similar.
struct Node *insert(struct Node *listp, int pos, int info)
{
/*Inserts a Node in list at position pos with data info
pos>0. If pos>list length then new node added at end.
If pos<1 adds at beginning.
*/
struct Node *new=malloc(sizeof(struct Node)), *prev;// new is the new node we create everytime.
//create new node and initialize fields
new->data=info;
new->next=NULL;
if (listp==NULL) listp=new;
else
if (pos<=1) { //negative or 1 index.
new->next=listp; //first node bann gaya new
listp=new; //head is pointing at new
}
else {
//pos>1. Go to node at pos-1.
prev=listp;
int i=1;
while ((i++<pos-1) && prev->next!=NULL) { //indexing
prev=prev->next;
}
new->next=prev->next;
prev->next=new;
}
return listp;
}
how do I address this problem?
To implement a doubly linked list, your node needs to have pointers to the previous node and next node, then you can write something almost as similar to what your professor gave you for single linked list:-
#include <stdlib.h>
#include <stdio.h>
//Doubly linked list Node
typedef struct Node{
int info;
struct Node* next;
struct Node* prev;
} Node;
Node* insert(Node* listp, int pos, int info){
//Allocate memory for node and its previous neighbor
Node* new = malloc(sizeof(Node));
Node* prev = malloc(sizeof(Node)), *tail;
//initialize new node with these values
new->info = info;
new->next = NULL;
new->prev = NULL;
//if head doesn't exist then create one
if(listp == NULL){
/*
listp gets whatever new had, ie
listp->info = info
listp->next = NULL
listp->prev = NULL
*/
Node* tail = malloc(sizeof(Node));
tail->info = 0;
tail->next = NULL;
tail->prev = NULL;
listp = new;
listp->next = tail;
tail->prev = listp;
}
//Lets Loop through the List and insert node at pos
else {
if(pos <= 1){
/*
This should replace the current head
listp = new
*/
new->next = listp;
new->prev = listp->prev;
listp->prev = new;
listp = new;
}
else{
int i = 2;
prev = listp->next;
printf("%d\n", prev->prev->info);
while(i != pos){
printf("%d\n", new->info);
prev = prev->next;
i++;
}
new->next = prev;
new->prev = prev->prev;
prev->prev->next = new;
prev->prev = new;
}
}
return listp;
}
// Test case
int main(){
Node* listp;
listp = insert(NULL, 0, 2);
listp = insert(listp, 1, 3);
listp = insert(listp, 2, 5);
Node* cnt = listp;
printf("|");
while(cnt->next != NULL){
printf("--%d-->", cnt->info);
cnt = cnt->next;
}
printf("\n");
}
Try that. Make any typo corrections if any
#include <stdio.h>
#include <stdlib.h>
/**
* add_node_end - adds a new node at the end of a dllist list
* #head: head of linked list
* #n: integer value of node
*
* Return: address of new element, NULL if fails
*/
node *add_node_end(node **head, const int n)
{
node *new, *temp;
new = malloc(sizeof(node));
if (new == NULL)
return (NULL);
new->n = n;
new->next = NULL;
if (*head == NULL)
{
new->prev = NULL;
*head = new;
return (*head);
}
temp = *head;
while (temp->next)
{
temp = temp->next;
}
temp->next = new;
new->prev = temp;
return (new);
}
/**
* add_dnodeint - adds a new node at the beginning of a dlistint_t list
* #head: head of linked list
* #n: integer value of node
*
* Return: address of new element, NULL if fails
*/
node *add_node_start(node **head, const int n)
{
node *new;
new = malloc(sizeof(node));
if (new == NULL)
return (NULL);
new->n = n;
new->prev = NULL;
if (*head == NULL)
{
new->next = NULL;
*head = new;
return (*head);
}
new->next = *head;
(*head)->prev = new;
*head = new;
return (*head);
}
/**
* node_len - returns the number of elements in a dllist list
* #h: head of doubly linked list
*
* Return: number of nodes
*/
size_t node_len(const node *h)
{
int count = 0;
while (h)
{
count++;
h = h->next;
}
return (count);
}
/**
* insert_dnodeint_at_index - inserts a new node at a given position
* #h: a pointer to a pointer of the first node of node linked list
* #index: the position to add the new node
* #val: the data n of the new node
* Return: if the function fails = NULL
* otherwise - the address of the new node/element
*/
node *insert_dnodeint_at_index(node **h, unsigned int index, int val)
{
node *newNode, *current;
size_t list_length;
unsigned int i = 0;
if (h == NULL)
return (NULL);
if (index == 0)
return (add_node_start(h, n));
list_length = node_len(*h);
if (index == (list_length - 1))
return (add_node_end(h, n));
newNode = malloc(sizeof(node));
if (newNode == NULL)
return (NULL);
newNode->val = val;
if (*h == NULL)
{
newNode->prev = NULL;
newNode->next = NULL;
return (newNode);
}
current = *h;
while (current)
{
if (i == index)
{
newNode->next = current;
newNode->prev = current->prev;
current->prev->next = newNode;
current->prev = newNode;
return (newNode);
}
current = current->next;
i++;
}
free(newNode);
return (NULL);
}

Polynominal with doubly linked list - pointer problem

I made some polynomial code with a doubly-linked list. for example, if
you write 1 and 2 then 1 is a degree and 2 is coefficient. 1x^2 insert
to doubly linked list. the problem is that when I check my code, the Node
head->degree is changing. if I write 1x^2 then head->degree is 1 next,
I write 2x^1 then head-> degree should maintain 1 but head-> degree
change to 2 I think there is some problem in the head pointer.
#include <stdio.h>
#include <stdlib.h>
// struct
struct Node {
int degree;
int coefficient;
struct Node* next;
struct Node* prev;
};
// global variables
int de; // degree
int co; // coefficient
int flag;
Node** head = (Node**)malloc(sizeof(Node)); //
Node** head1 = (Node**)malloc(sizeof(Node)); //
Node** head2 = (Node**)malloc(sizeof(Node)); //
Node** head3 = (Node**)malloc(sizeof(Node)); //
Node* newNode = (Node*)malloc(sizeof(Node)); //
// function
Node* inputpoly(void);
void printNode(Node* inp);
Node* multiply(Node* a, Node* b);
// main
int main() {
// head null
(*head1) = NULL;
(*head2) = NULL;
(*head3) = NULL;
while (1) {
printf("Input (degree) (coefficient) : ");
scanf_s("%d %d", &de, &co);
if (de * co < 0) { continue; }
if (de < 0 && co < 0) {
printf("Done!\n");
break;
}
*head = inputpoly();
}
printNode(*head);
//multiply(*head1, *head2);
free(head1);
free(head2);
free(head3);
free(newNode);
free(head);
}
Node* inputpoly(void) {
// create Node
newNode->degree = de;
newNode->coefficient = co;
newNode->next = NULL;
newNode->prev = NULL;
// case1
if (flag == 0) {
// list
if ((*head1) == NULL) {
*head1 = newNode;
}
// list x
else {
Node* horse = (*head1);
// front of head
// ------------------There is some problem
printf("%d\n", 1);
printf("--%d\n", newNode->degree);
printf("--%d\n", horse->degree);
if (horse->degree > newNode->degree) {
newNode->next = horse;
horse->prev = newNode;
*head1 = newNode;
}
// barward of head
else {
int num = 0;
while (horse->next != NULL) {
horse = horse->next;
if (horse->degree > newNode->degree) {
horse->prev->next = newNode;
newNode->next = horse;
newNode->prev = horse->prev;
horse->prev = newNode;
num = 1;
break;
}
}
// behind tail
if (num == 0) {
horse->next = newNode;
newNode->prev = horse;
}
}
}
return *head1;
}
}
void printNode(Node* inp) {
Node* horse = inp;
if (horse == NULL)
{
return;
}
while (horse != NULL) {
if (horse->prev == NULL) {
if (horse->degree == 1) {
printf("%d", horse->coefficient);
}
else {
printf("%d x^%d", horse->coefficient, horse->degree);
}
}
else {
if (horse->degree == 1) {
printf(" + %d", horse->coefficient);
}
else {
printf(" + %d x^%d", horse->coefficient, horse->degree);
}
}
}
printf("\n");
}
"i think there is some head pointer problem, and if I fixed it I can this problem. so I want to maintain this code as possible. I want some
advice or solution to my head pointer"
The code posted in your example does not compile:
Before you can fix a head pointer problem the code must compile. This list of errors is detailing 2 things:
first, functions cannot be called outside of a function, eg:
Node** head = (Node**)malloc(sizeof(Node)); //
Node** head1 = (Node**)malloc(sizeof(Node)); //
Node** head2 = (Node**)malloc(sizeof(Node)); //
Node** head3 = (Node**)malloc(sizeof(Node)); //
Node* newNode = (Node*)malloc(sizeof(Node)); //
should be called from within main(void){...} or some other function.
second, every occurrence of Node should be prepended with struct. eg:
struct Node** head = malloc(sizeof(struct Node *));
(have also removed the cast, and modified the size of what you are creating memory for, i.e. a pointer)
Rather then fix these and other problems, here is an example of a doubly linked list that can demonstrate the structure of a simple working program. You can adapt the following to match your needs:
struct Node {
int deg;
int coef;
struct Node* next; // Pointer to next node in DLL
struct Node* prev; // Pointer to previous node in DLL
};
void inputpoly(struct Node** head_ref, int deg, int coef)
{
//allocate node
struct Node *new_node = malloc(sizeof(*new_node));
//assign data
new_node->deg = deg;
new_node->coef = coef;
//set next as new head and prev to null
new_node->next = (*head_ref);
new_node->prev = NULL;
//change prev of head to new */
if ((*head_ref) != NULL)
(*head_ref)->prev = new_node;
//point head to the new node */
(*head_ref) = new_node;
}
void printList(struct Node* node)
{
struct Node* last;
printf("\nread forward\n");
while (node != NULL) {
printf(" %d,%d ", node->deg,node->coef);
last = node;
node = node->next;
}
printf("\nread reverse\n");
while (last != NULL) {
printf(" %d,%d ", last->deg,last->coef);
last = last->prev;
}
}
int main(void)
{
//start with empty list
struct Node* head = NULL;
//create and populate new nodes
inputpoly(&head, 7, 2);
inputpoly(&head, 1, 4);
inputpoly(&head, 4, 6);
//ouput list
printList(head);
getchar();
return 0;
}
Note that this code is offered as a basic demonstration of creating doubly linked list, and illustrate how to traverse both directions. Because it does not free allocated memory, it is not recommended that it be used for any production purpose without addressing that omission.

Inserting in Binary Search Tree (C) using for loop

I'm having trouble inserting in a Binary Search Tree using for loop, when I call the InorderTraversal function, there is no output all I get is a blank line, as far as I think rest of the code is okay the only problem is in the insert function.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct BinaryTree{
int data;
struct BinaryTree *left;
struct BinaryTree *right;
} node;
node* Insert(node* head, int value)
{
_Bool flag = true;
for(node *temp = head; flag == true; (temp = (value >= temp->data)?(temp->right):(temp->left)))
{
if(temp == NULL)
{
temp = (node*)malloc(sizeof(node*));
temp->data = value;
temp->left = NULL;
temp->right = NULL;
flag = false;
}
}
return head;
}
void InorderTraversal(node* head)
{
if(head == NULL)
{
return;
}
InorderTraversal(head->left);
printf("%d ",head->data);
InorderTraversal(head->right);
}
int main(void)
{
node *head = NULL;
for(int i = 0; i < 40; i++)
{
head = Insert(head,i);
}
InorderTraversal(head);
return 0;
}
Here try these changes in your Insert function
node* Insert(node *head, int value)
{
if(!head) //Explicitly insert into head if it is NULL
{
head = malloc(sizeof *head);
head->data = value;
head->left = NULL;
head->right = NULL;
return head;
}
for(node *temp = head,*temp2 = head; ;(temp = (value >= temp->data)?(temp->right):(temp->left)))
{
if(temp == NULL)
{
temp = malloc(sizeof *temp);
temp->data = value;
temp->left = NULL;
temp->right = NULL;
if(value >= temp2->data) //update previous nodes left or right pointer accordingly
temp2->right = temp;
else
temp2->left = temp;
break;
}
temp2 = temp; //Use a another pointer to store previous value of node
}
return head;
}
Call me crazy, but shouldn't that malloc(sizeof(node*)) be malloc(sizeof node)?
I am not that so informed, other than being able to read C, so excuse me if this is simply wrong...
Edit: ... or malloc(sizeof * temp)
When you insert the first node you dereference an uninitialized pointer here:
temp->data
Where temp is head and head in uninitialized and pointing to NULL.
So you first have to make special case when head is NULL:
if( !head )
{
head = malloc(sizeof(node));
head->data = value;
head->left = NULL;
head->right = NULL;
return head ;
}
When you continue adding elements you don't update the pointer of the last node. Your for loop should have an extra pointer to the previous node and when you get to the last node and find NULL update the previous nodes left or right pointer.
if(temp == NULL) //wrong, should be: not equal
{
temp = (node*)malloc(sizeof(node*)); //wrong, should be: sizeof the node not the pointer
temp->data = value;
temp->left = NULL;
temp->right = NULL;
flag = false; //use break instead
}
here the previous node pointer left or right is not updated and when you search you can't find any node.

Resources