QuickSorting Linked Lists in C - c

I am trying to become more familiar with recursion and I am trying to write a function recursively rather than iteratively... I am trying to create a quick-sort function for linked list, I keep reevaluating the code, but I don't know what I am missing, the code always leaves the last node on the list, for example...
input list ... 1->2->3->4->NULL
output list .. 4->NULL
here is my code ...
void lst_qsort(LIST *l){
if(l==NULL || l->front==NULL || l->front->next==NULL)
return;
if(lst_length(l)<=1)
return;
LIST *lt = lst_create();
LIST *pivot = lst_create();
pivot->front = l->front;
pivot->back = l->front;
l->front = l->front->next;
pivot->front->next = NULL;
lt = lst_filter_leq(l, pivot->front->val);
lst_qsort(lt);
lst_qsort(l);
lst_concat(l, lt);
}
NOTES lst_filter_leq() is a function that pulls out all occurrences of x<=cutoff point and returns a list of all the nodes pulled.
LIST * lst_filter_leq(LIST *lst, ElemType cutoff) {
LIST *lst2 = lst_create();
NODE *tmp = lst->front;
int i = 0, n=1;
while(lst->front != NULL){
if(lst->front->val <= cutoff){
lst_push_back(lst2, lst->front->val);
}
lst->front = lst->front->next;
}
lst->front = tmp;
for(i=cutoff; i>=0; i--){
n = lst_remove_all_slow(lst, i);
}
return lst2;
}
lst_concat() merges two list together

Look at your code and your example. First, looks like creating pivot list is seemingly not necessary, as you use only pivot->front->val, which I assume is the first value on your list (because you earlier did pivot->front = l->front).
So for values [1, 2, 3, 4] you do the following in the first step (I use pseudo-code to show list members):
// you extracted '1' from your list, because you did l->front = l->front->next;
lt = lst_filter_leq([2, 3, 4], 1);
which means you end with nothing (none of the values on the list are less or equal than 1). Next you do quicksort of l (which is [2, 3, 4]) and then concatenate results of l and lt.
But when quicksorting [2, 3, 4] you receive nothing and quicksort [3, 4],
which is nothing and [4].
And quicksorting of [4] returns [4]. Hence your result.
So looks what you forgot was inserting pivot between l and lt lists.
Working implementation using glib library for double-ended queues:
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
// defines to maintain compatibility with OP code
#define LIST GQueue
#define lst_create g_queue_new
#define lst_length g_queue_get_length
// lst_push_back implementation using GQueue
void lst_push_back(LIST *list, int val) {
g_queue_push_tail(list, GINT_TO_POINTER(val));
}
// lst_pop_front implementation using GQueue
int lst_pop_front(LIST *list) {
return GPOINTER_TO_INT(g_queue_pop_head(list));
}
// adds elements from list2 to list1
// list2 is destroyed afterwards
void lst_concat(LIST *list1, LIST *list2) {
int length = lst_length(list2);
int i, v;
for (i = 0; i < length; ++i) {
v = lst_pop_front(list2);
lst_push_back(list1, v);
}
g_queue_free(list2);
}
// filters 'list' elements
// elements less or equal 'value' are returned in newly created list
// elements greater than 'value' are left in 'list'
LIST *lst_filter_leq(LIST *list, int value) {
LIST *lte = lst_create();
LIST *gt = lst_create();
int length = lst_length(list);
int i, v;
for (i = 0; i < length; ++i) {
v = lst_pop_front(list);
if (v <= value) {
lst_push_back(lte, v);
} else {
lst_push_back(gt, v);
}
}
lst_concat(list, gt);
return lte;
}
void lst_qsort(LIST *l) {
if (l == NULL) {
return;
}
if (lst_length(l) <= 1) {
return;
}
LIST *lt = lst_create();
LIST *pivot = lst_create();
int val = lst_pop_front(l);
lst_push_back(pivot, val);
// this function divides the list int two parts
// elements less or equal 'val' are returned in lt list ("right" list)
// elements greater than 'val 'are left in l list ("left" list)
lt = lst_filter_leq(l, val);
lst_qsort(lt); // sort "right" part of list
lst_qsort(l); // sort "left" part of list
lst_concat(l, pivot); // add the pivot element
lst_concat(l, lt); // add right part of list
}
void printList(LIST *list) {
GList *vList = g_queue_peek_head_link(list);
while (vList != NULL) {
printf("%d", GPOINTER_TO_INT(vList->data));
vList = g_list_next(vList);
if (vList != NULL) {
printf("->");
} else {
printf("\n");
}
}
}
int main(void) {
LIST *l = lst_create();
lst_push_back(l, 4);
lst_push_back(l, 3);
lst_push_back(l, 2);
lst_push_back(l, 1);
printf("unsorted: ");
printList(l);
lst_qsort(l);
printf("sorted: ");
printList(l);
g_queue_clear(l);
lst_push_back(l, 1);
lst_push_back(l, 2);
lst_push_back(l, 3);
lst_push_back(l, 4);
printf("unsorted: ");
printList(l);
lst_qsort(l);
printf("sorted: ");
printList(l);
g_queue_clear(l);
srand(time(NULL));
int i;
for (i = 0; i < 16; ++i) {
lst_push_back(l, rand() % 32);
}
printf("unsorted: ");
printList(l);
lst_qsort(l);
printf("sorted: ");
printList(l);
g_queue_free(l);
return 0;
}
Example output:
unsorted: 4->3->2->1
sorted: 4->3->2->1
unsorted: 1->2->3->4
sorted: 4->3->2->1
unsorted: 27->16->20->4->14->30->26->28->10->13->19->1->30->8->3->14
sorted: 30->30->28->27->26->20->19->16->14->14->13->10->8->4->3->1

Related

Printing random numbers to list

My task is to generate random numbers in range from 50 to 80, if generated number is even add it to list of even numbers, if it is odd add it to list of odd numbers. Program should run till both lists are filled with 10 numbers. Duplicates in list are not allowed. This code prints 20 different numbers and it is storing duplicates in list. So I think problem is with count_odd, count_even and checking for duplicates but I can’t find solution to that. Also I have to print all generated numbers and also both lists in the end. Numbers in linked list should be in descending order
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
typedef struct list numbers;
typedef struct list* Pos;
int PrintRandom();
Pos CreateNew();
int PrintList(Pos);
struct list {
int number;
Pos next;
};
int PrintList(Pos P) {
if (P == NULL)
printf("Empty list.\n");
while (P != NULL) {
printf("%d\n", P->number);
P = P->next;
}
return 0;
}
Pos CreateNew() {
Pos q = NULL;
q = (Pos)malloc(sizeof(struct list));
if (q == NULL) return NULL;
q->next = NULL;
return q;
}
int PrintRandom() {
int x = 0, max = 80, min = 50;
x = (rand() % (max - min + 1) + min);
printf("Random number is : %d\n", x);
return x;
}
int main() {
srand(time(0));
Pos even, odd, q = NULL;
even = malloc(sizeof(numbers));
odd = malloc(sizeof(numbers));
even->next = odd->next = NULL;
int count_even = 0, count_odd = 0, j;
Pos head_p =even, head_n=odd;
while (count_even < 10 & count_odd < 10) {
j = PrintRandom();
if (j % 2 == 0) {
q = CreateNew();
if (q == NULL) return -1;
q->number = j;
while (even->next != NULL && even->next->number > q->number) {
even = even->next;
}
if (even->number== q->number)
free(q);
else
q->next = even->next;
even->next = q;
even =head_p;
count_even++;
}
else {
q = CreateNew();
if (q == NULL) return -1;
q->number = j;
while (odd->next != NULL && odd->next->number > q->number) {
odd = odd->next;
}
if (odd->number == q->number)
free(q);
else
q->next = odd->next;
odd->next = q;
odd = head_n;
count_odd++;
}
}
printf("Even numbers in list are:\n");
PrintList(head_p->next);
printf("Odd numbers in list are:n");
PrintList(head_n->next);
return 0;
}
Your code has several bugs:
First bug:
The loop
while (count_even < 10 & count_odd < 10) {
will stop as soon as either count_even or count_odd reaches 10. However, in your question, you stated that the loop should only stop when both have reached 10.
Therefore, you should change that line to the following:
while ( count_even < 10 || count_odd < 10 ) {
Also, it is worth pointing out that & is the bitwise-AND operator. You probably intended to use the logical-AND operator, which is &&.
Second bug:
In the comments section, you stated that if one of the lists is already full (has 10 elements), then all additional numbers that belong in that list should be discarded instead. However, your program does not contain any code to check for this. Instead, your program will keep adding new elements to the list, even if it already has 10 elements.
Third bug:
The following code is wrong:
if (even->number== q->number)
free(q);
else
q->next = even->next;
even->next = q;
even =head_p;
count_even++;
First of all, you should change the expression
even->number== q->number
to:
even->next->number== q->number
However, since even->next may be null, you must test for that beforehand, so that the entire line would look like this:
if ( even->next != NULL && even->next->number== q->number)
Also, the lines
even->next = q;
and
count_even++;
should not be executed if the number already exists. Therefore, you should move these lines inside the else block. After performing these changes, your code should look like this:
if ( even->next != NULL && even->next->number== q->number)
{
free(q);
}
else
{
q->next = even->next;
even->next = q;
count_even++;
}
even =head_p;
The same changes should be performed on the code branch for the odd numbers.
Fourth Bug:
There is a backslash character missing in the following line:
printf("Odd numbers in list are:n");
You should change it to:
printf("Odd numbers in list are:\n");
Additional remarks:
There are two other things that I think could be improved in your code:
The first element of the linked list is just a dummy node in which the number field is not initialized. You seem to be using this node for nothing else than holding the head pointer to the actual linked list.
You have a lot of code duplication. Instead of using the same code for handling both even and odd numbers, you have separate, but very similar code for handling each case.
In the code below, I have rewritten most of your code to show you can see how I would solve this problem. Don't be surprised if you find it hard to understand, as I am using pointers to pointers, which can be hard for beginners to understand. As you can see, I am not using any dummy nodes, and I am also using the same code for handling both even and odd numbers. Only in two places of my code do I have different code for handling even and odd numbers.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
struct list_node
{
int number;
struct list_node *next;
};
int PrintRandom();
int PrintList( struct list_node * );
int PrintList( struct list_node *p)
{
if ( p == NULL )
{
printf( "Empty list.\n" );
}
else
{
while ( p != NULL )
{
printf( "%d\n", p->number );
p = p->next;
}
}
return 0;
}
int PrintRandom() {
int x = 0, max = 80, min = 50;
x = (rand() % (max - min + 1) + min);
printf("Random number is : %d\n", x);
return x;
}
int main()
{
srand( (unsigned)time(NULL) );
struct list_node *head_even = NULL, *head_odd = NULL;
int count_even = 0, count_odd = 0, random;
bool is_even;
while ( count_even < 10 || count_odd < 10 )
{
struct list_node **pp, *p, *q;
//generate and print random number
random = PrintRandom();
//determine whether number is even or odd
is_even = random % 2 == 0;
//set pp to point to head pointer of the appropriate list
//and check whether the appropriate list is already full
if ( is_even )
{
if ( count_even >= 10 )
continue;
pp = &head_even;
}
else
{
if ( count_odd >= 10 )
continue;
pp = &head_odd;
}
for (;;) //infinite loop, equivalent to while (1)
{
p = *pp;
//if we reached the end of the list, break out of the loop
if ( p == NULL )
break;
if ( p->number <= random )
{
if ( p->number == random )
{
//discard number, because it already exists in list
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto next_outer_loop_iteration;
}
else
{
break;
}
}
pp = &p->next;
}
//allocate memory for new node
q = malloc( sizeof *q );
if ( q == NULL)
{
fprintf( stderr, "error allocating memory for new node!\n" );
exit( EXIT_FAILURE );
}
//initialize new node
q->number = random;
q->next = p;
//insert node into list
*pp = q;
//increment the appropriate counter
if ( is_even )
count_even++;
else
count_odd++;
next_outer_loop_iteration:
continue;
}
printf("Even numbers in list are:\n");
PrintList( head_even );
printf("Odd numbers in list are:\n");
PrintList( head_odd );
//NOTE: The memory of the linked lists is not being freed
return 0;
}

Implementing Binary search tree using array in C

I am trying to implement a binary search tree using a 1-D array. I'm familiar with the fact that the left node will be parent*2+1 and right node will be parent*2+2. I am using this concept to write the insertion function here:
int* insert(int tree[], int element){
int parent=0;
if(tree[parent]=='\0'){
tree[parent]=element;
return tree;
}
else{
if(element<tree[parent]){
parent=parent*2+1;
tree[parent]=insert(tree[parent], element);
}
else{
parent=parent*2+2;
tree[parent]=insert(tree[parent], element);
}
}
return tree;
}
However, I'm quite sure this won't work, since I'm passing an element of the array into the insert() function while recursing, when it actually needs an array. I'm not sure how to go about it. Do I replace the return type from int* to int? Any help is appreciated
the fact that the left node will be parent2+1 and right node will be parent2+2
That's correct. You want to use the array index like
0
/ \
/ \
/ \
/ \
1 2
/ \ / \
/ \ / \
3 4 5 6
But your recursion is not doing that.
You always do int parent=0; so you have no knowledge of the real array index and consequently, you access the wrong array elements.
For instance:
When you pass tree[2] you really want the function to use either tree[5] or tree[6] in the next recursive call. However, since you start by setting parent to zero, your next recursive call will us either tree[3] or tree[4].
Conclusion If you want to use recursion, you need to track the actual array index of the current node. Simply passing a pointer to the current node is not sufficient.
Instead your code could be:
int insert(int* tree, unsigned current_idx, int element){
if (current_idx >= ARRAY_SIZE) return -1;
if(tree[current_idx]=='\0'){
tree[current_idx]=element;
return 0;
}
if(element<tree[current_idx]){
return insert(tree, 2*current_idx + 1, element);
}
return insert(tree, 2*current_idx + 2, element);
}
That said - you should also spend some time considering whether recursion is really a good solution for this task.
Without recursion you can do:
int insert(int* tree, int element){
unsigned current_idx = 0;
while (1)
{
if (current_idx >= ARRAY_SIZE) return -1;
if(tree[current_idx]=='\0'){
tree[current_idx]=element;
return 0;
}
if(element<tree[current_idx]){
current = 2*current_idx + 1;
}
else {
current = 2*current_idx + 2;
}
}
}
As you can see the recursive approach didn't give you anything. Instead it made things worse...
You can avoid recursion and do it iteratively. Note tree is actually an integer array of size size. In the function insert() we pass a pointer to the array. Assuming the array is initialized with 0s:
void insert(int* tree, int size, int element)
{
if (tree == NULL)
return;
int pos = 0;
while (pos < size)
{
if (tree[pos])
{
if (tree[pos] < element)
pos = 2 * pos + 2; // right
else if (tree[pos] && tree[pos] > element)
pos = 2 * pos + 1; // left
}
else
{
tree[pos] = element;
return;
}
}
}
Full code:
#include <stdio.h>
#include <stdlib.h>
void insert(int* tree, int size, int element)
{
if (tree == NULL)
return;
int pos = 0;
while (pos < size)
{
if (tree[pos])
{
if (tree[pos] < element)
pos = 2 * pos + 2; // right
else if (tree[pos] && tree[pos] > element)
pos = 2 * pos + 1; // left
}
else
{
tree[pos] = element;
return;
}
}
}
void print(int* tree, int size)
{
for (int i = 0; i < size; i++)
printf("%d ", tree[i]);
printf("\n");
}
int main()
{
int tree[100] = {0};
const int tsize = 100;
// print first 20 elements
print(tree, 20);
insert(tree, tsize, 2);
insert(tree, tsize, 3);
insert(tree, tsize, 5);
insert(tree, tsize, 1);
insert(tree, tsize, 4);
print(tree, 20);
return 0;
}

BST and Linked List C program stuck at large values

I'm doing a college work where the professor asked us to implement BST and linked list and count how many comparisons it makes to insert and search a large amount of randomly-generated values. We're supposed to start at 10 values, then 100, then 1000, up until 10^12. The thing is, it always gets stuck at 100000 (10^5). The RAM usage is low, but CPU is at max. I'm freeing both the tree and lists after each step. The code is found here (offsite) and below.
Just to sum up some important points: each value (the key to the node) is an unsigned it (max 65535), but up to 10^12 values should be inserted and another 10^12 searched.
Is it supposed to take this long? My processor is an i5-7200u
Is there a chance it's a memory problem and GCC is blocking it somehow?
Thanks a lot
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef long long ll;
typedef unsigned long long ull;
// BST
typedef struct no_A_struct {
unsigned int chave;
struct no_A_struct *esquerda;
struct no_A_struct *direita;
} no_A;
// new node
no_A *novo_no_A(unsigned int chave) {
no_A *no = (no_A *) malloc(sizeof(no_A));
no->chave = chave;
no->esquerda = no->direita = NULL;
return no;
}
// insert note
no_A *insere_A(no_A *raiz, unsigned int chave, ull *cont) {
(*cont)++; if (raiz == NULL) return novo_no_A(chave);
(*cont)++; if (chave < raiz->chave) raiz->esquerda = insere_A(raiz->esquerda, chave, cont);
else {
(*cont)++; if (chave > raiz->chave) raiz->direita = insere_A(raiz->direita, chave, cont);
}
return raiz;
}
// search node
no_A *busca_A(no_A *raiz, unsigned int chave, ull *cont) {
(*cont)++; if (raiz == NULL) return NULL;
(*cont)++; if (chave == raiz->chave) return raiz;
(*cont)++; if (chave > raiz->chave) return busca_A(raiz->direita, chave, cont);
return busca_A(raiz->esquerda, chave, cont);
}
// free tree
void desaloca_A(no_A *raiz) { // TODO iterativa?
if (raiz == NULL) return;
desaloca_A(raiz->esquerda);
desaloca_A(raiz->direita);
free(raiz);
}
// LINKED LIST WITH IN ORDER INSERTION
typedef struct no_L_struct {
unsigned int chave;
struct no_L_struct *prox;
} no_L;
// new node
no_L *novo_no_L(unsigned int chave) {
no_L *no = (no_L *) malloc(sizeof(no_L));
no->chave = chave;
no->prox = NULL;
return no;
}
// insert node
void insere_L(no_L **inicio, unsigned int chave, ull *cont) {
no_L *novo_no = novo_no_L(chave);
(*cont)++; if (*inicio == NULL) { *inicio = novo_no; return; }
(*cont)++; if (novo_no->chave <= (*inicio)->chave) {
novo_no->prox = *inicio;
*inicio = novo_no;
} else {
no_L *atual = *inicio;
for (;;) {
(*cont)++; if (atual->prox == NULL) break;
(*cont)++; if (novo_no->chave <= atual->prox->chave) break;
atual = atual->prox;
}
novo_no->prox = atual->prox;
atual->prox = novo_no;
}
}
// search node
no_L *busca_L(no_L *atual, unsigned int chave, ull *cont) {
for (;;) {
(*cont)++; if (atual == NULL) break;
(*cont)++; if (atual->chave == chave) break;
atual = atual->prox;
}
return atual;
}
// void printa_L(no_L *atual) {
// if (atual == NULL) return;
// printf("%u", atual->chave);
// printa_L(atual->prox);
// }
// free list
void desaloca_L(no_L *atual) {
no_L *no_apagar;
while (atual != NULL) {
no_apagar = atual;
atual = atual->prox;
free(no_apagar);
}
}
int main() {
ll QTD_VALORES[] = {10, 100, 1000, // 10^: 1, 2, 3
10000, 100000, 1000000, // 4, 5, 6
1000000000, 10000000000, // 9, 10
100000000000, 1000000000000}; // 11, 12
int ITERACOES = 1; // TODO voltar pra 100
unsigned int VALOR_MAX = 65535;
int tamanho_qtd_valores = sizeof(QTD_VALORES)/sizeof(QTD_VALORES[0]);
srand(time(0));
for (int qtd_i=0; qtd_i<tamanho_qtd_valores; qtd_i++) {
ll qtd = QTD_VALORES[qtd_i];
printf("== QTD DE VALORES %lli ==\n", qtd);
for (int i=0; i<ITERACOES; i++) {
ull comp_A_insercao = 0, comp_A_busca = 0,
comp_L_insercao = 0, comp_L_busca = 0;
no_A *arvore = NULL;
no_L *lista = NULL;
// generates and insert values
unsigned int valores_busca[qtd];
for (ll v=0; v<qtd; v++) {
// // insert values
unsigned int valor_insercao = rand() % VALOR_MAX + 1;
arvore = insere_A(arvore, valor_insercao, &comp_A_insercao);
insere_L(&lista, valor_insercao, &comp_L_insercao);
valores_busca[v] = rand() % VALOR_MAX + 1;
}
// search values
for (ll v=0; v<qtd; v++) {
busca_A(arvore, valores_busca[v], &comp_A_busca);
busca_L(lista, valores_busca[v], &comp_L_busca);
}
// desaloca_A(arvore);
// desaloca_L(lista);
// TODO divisões retornar numero real?
printf("INTERACTION %d: \n", i+1);
printf("Tree insertion, total=%llu, avg=%llu\n", comp_A_insercao,
comp_A_insercao / qtd);
printf("Tree search, total=%llu, avg=%llu\n", comp_A_busca,
comp_A_busca / qtd);
printf("List insertion, total=%llu, avg=%llu\n", comp_L_insercao,
comp_L_insercao / qtd);
printf("List search, total=%llu, avg=%llu\n", comp_L_busca,
comp_L_busca / qtd);
}
printf("\n");
}
}
Are you sure you are supposed to insert items already in the list? I think you're suppose to avoid adding duplicates keys.
Inserting the first node in the linked list will requires 0 comparisons. The second, 1/2 (on avg). The third, 2/2, The fourth 3/2, etc. So inserting N times will have a average time proportional to (0+1+2+...+(N-2)+(N-1))/2 = N*(N-1)/4.
$ perl -e'printf "%d: %d\n", $_, (10**$_)*(10**$_-1)/4 for 1..5;'
1: 22
2: 2475
3: 249750
4: 24997500
5: 2499975000
That's an average time of 2.5 billion time units to insert 105 nodes. For example, if it takes 100 ns per comparison, it will take over 4 minutes to insert 105 nodes on average.
At that same rate, inserting 1012 nodes would take an average of 800 million years.
If, on the other hand, you avoid adding a key that's already in the list, the average time will be no more than 65,536*N/2
$ perl -e'printf "%d: %d\n", $_, 65536*(10**$_-1)/4 for 1..12;'
1: 147456
2: 1622016
3: 16367616
4: 163823616
5: 1638383616
6: 16383983616
7: 163839983616
8: 1638399983616
9: 16383999983616
10: 163839999983616
11: 1638399999983616
12: 16383999999983616
So instead of taking 800 million years, inserting 1012 nodes will take an average of "only" 19 days using the rate assumed above. Even if I'm off by an order of magnitude, we're still talking about 2 days.

C Bubblesort in LinkedList

I'm trying to sort a doubly linked list, but I'm having some trouble. I'm a noob in C and I guess my problem is with pointers..
I just can't see how to swap two positions inside the list and so maybe that's the issue.
I tryied to sort it by using Bubblesort, even knowing that it's complexity is not so good because, how I'm still learning, thought that it was an easy way to start.
I also tryied reading some things about swaping elements in a linkedlist and how to sort them, but I'm really stuck with this problem...
PS: I started the for with the m->next cause my list has a header(m).
PS2:I'm getting the error "request for member ‘next’ in something not a structure or union", and don't know how to fix it
struct segment {
int x, y; /// position
char c; // letter
struct segment* next;
struct segment* prev;
};
void sortingSegments(struct segment* m) {
struct segment **j; struct segment **i;
for(i = &((m->next)->next); i !=NULL; i = i->next) {
for(j = &(m->next); j == i; j = j->next) {
if ((*j)->c > (*i)->c) {
struct segment **aux;
aux = i;
(*aux)->next = (*i)->next;
(*aux)->prev = (*i)->prev;
i = j;
(*i)->next = (*j)->next;
(*i)->prev = (*j)->prev;
j = aux;
(*j)->prev = (*aux)->prev;
(*j)->next = (*aux)->next;
}
}
}
}
Please read the comments and try to understand the linking of nodes.
It is based on the simple bubble sort described in wikipedia.
void sortingSegments(struct segment** m) {
struct segment *i, *tmp, *prev, *next;
int swapped = 1;
/*
* https://en.wikipedia.org/wiki/Bubble_sort#Pseudocode_implementation
* n = length(A)
* repeat
* swapped = false
* for i = 1 to n-1 inclusive do
* //if this pair is out of order
* if A[i - 1] > A[i] then
* // swap them and remember something changed
* swap(A[i - 1], A[i])
* swapped = true
* end if
* end for
* until not swapped
*/
// looping until no more swaps left
while (swapped) {
swapped = 0;
// we begin from the second item at each iteration
for (i = (*m)->next; i; i = i->next) {
// we need to swap i with i->prev
if (i->prev->c > i->c) {
prev = i->prev;
next = i->next;
// swapping first and second elements,
// so update m to reflect the change made
// to the head of the list
if (prev == *m) {
*m = i;
}
// so there is a prev of prev, update that two links
else {
prev->prev->next = i;
i->prev = prev->prev;
}
// so there is a next, update that two links
if (next) {
next->prev = prev;
prev->next = next;
}
// no next element, mark the end of the list
else {
prev->next = NULL;
}
// this is obvious, prev now becomes i's next
prev->prev = i;
i->next = prev;
// this is needed to reflect the change in i
i = prev;
swapped = 1;
}
}
}
}

a c program to add two singly linked lists, of unequal lengths containing single digited numbers in all of their nodes

i got this as an interview question. i was given 2 linked lists of unequal lengths,containing a single digited number in each of their nodes. i was asked to build a 3rd linked list which contains the sum of the two linked lists, again in the form of 1 digit in a node.
ex:
linked list 1 is
4-7-9-6
linked list 2 is
5-7
then the 3rd linked list would be
4-8-5-3
can someone suggest me an efficient algorithm, with minimum compromise in terms of space complexity?(i am not expecting an algo dat involves reversing the lists many times).
Reverse lists 1 and 2
Sum element-by-element (while
maintaining a carry), putting the
results in a list 3 that you
construct from tail to head
OR
Convert lists 1 and 2 to ints (e.g. int list1AsInt = 0; For each node {list1AsInt *= 10; list1AsInt += valueOfThisNode;} )
Sum those ints
Convert the result to a linked list (e.g. valueOfBrandNewNode = list3AsInt % 10; list3AsInt /= 10; Add a new node that points to the prev one; )
OR
Traverse both lists once to find out
their lengths. For this example,
let's assume that list 1 is longer
by N nodes.
Create a list 3 to represent the sum
without carries and a list 4 to
represent the carries.
For the first N nodes of list 1,
copy those values to list 3 and make
list 4's values be 0.
For the remaining nodes of lists 1
and 2, sum element-by-element,
putting the sum mod 10 in list 3 and
the carry in list 4. Keep track via
a bool of whether list 4 is all 0's.
Add a last node with value 0 to list
4.
If list 4 is entirely 0's, done.
Else, recurse to step 2,
treating list 3 as
the new list 1 and list 4 as the new
list 2. We know the length of the
new list 1 is the larger of the lengths
of the old lists 1 and 2, and the length
of the new list 2 is one more than that.
Read each digit as its ASCII equivalent into a char array indexed from 0, for both lists.
Use the atoi() function on both char arrays ( you may use atol() or atoll() if you are concerned about the length)
Add both numbers
Use the itoa() function to convert to a char array & then put back into new list.
Although, I admit the itoa() function is not standard.
If the lists are doubly linked it's easy:
Traverse both lists to the end.
Add the digits in corresponding nodes, and keep the carry digit.
Create the node in list 3.
Move one node towards the start of the lists and repeat.
The solution could be much simpler if the list stored the numbers in reverse order.
Nevertheless, with the given constraint, here is an approach.
find the nthToLast digit of both lists, starting with n = 0,
create a node with the sum of the digits,
update the (running) carry,
insert the newly created node at the head of the result list
Following is the (untested) C code.
typedef struct DigitNode_ {
int digit;
struct DigitNode_ * next;
} DigitNode;
/* Returns the n-th element from the end of the SLL;
if no such element exists, then return NULL.
See: https://stackoverflow.com/questions/2598348/
*/
extern DigitNode * nthNodeFromTail( DigitNode * listHead, size_t n );
/* Push pNode in the front, i.e. as the new head of the list */
extern void pushFront( DigitNode ** pListHead, DigitNode * pNode );
/* Create new list as sum of a and b, and return the head of the new list.
a -> 4 -> 7 -> 9 -> 6 -> NULL
b -> 5 -> 7 -> NULL
results in
c -> 4 -> 8 -> 5 -> 3 -> NULL
*/
DigitNode * sumDigitLists( DigitNode * a, DigitNode * b ) {
DigitNode * c = 0;
int carry = 0;
/* i is the position of a node from the tail of the list, backwards */
for( size_t i = 0; /* see 'break' inside */; i++ ) {
const DigitNode * const ithNodeA = nthNodeFromTail( a, i );
const DigitNode * const ithNodeB = nthNodeFromTail( b, i );
/* Stop when processing of both lists are finished */
if( !ithNodeA && !ithNodeB ) {
break;
}
const int ithDigitA = ithNodeA ? ithNodeA->digit : 0;
const int ithDigitB = ithNodeB ? ithNodeB->digit : 0;
assert( (0 <= ithDigitA) && (ithDigitA <= 9) );
assert( (0 <= ithDigitB) && (ithDigitB <= 9) );
const int conceptualIthDigitC = carry + ithDigitA + ithDigitB;
const int ithDigitC = conceptualIthDigitC % 10;
carry = conceptualIthDigitC / 10;
DigitNode ithNodeC = { ithDigitC, NULL };
pushFront( &c, &ithNodeC );
}
return c;
}
Take a look at this code:
node *add_two_linkedlist(node *head1,node *head2)
{
int i,j,temp;
node *p,*n;
p=head1;
n=head2;
i=count(head1);
j=count(head2);
if(i>j)
{
while(j!=0)
{
p->data=p->data+n->data;
if(p->data>10)
{
temp=(p->data)/10;
p->data=(p->data)%10;
p=p->next;
n=n->next;
p=p->data+temp;
j--;
}
}
return head1;
}
if(j>i)
{
while(i!=0)
{
n->data=p->data+n->data;
if(n->data>10)
{
temp=(n->data)/10;
n->data=(n->data)%10;
n=n->next;
p=p->next;
n=n->data+temp;
i--;
}
}
return head2;
}
}
This is straightforward. Assuming the leftmost node is the most significant bit. Align the two lists, add and propagate carry. Upon return create a new node if required..
#include <stdio.h>
struct list {
int val;
struct list * next;
};
int listadd (struct list *l1, struct list *l2) {
if ((l1 == NULL) || (l2 == NULL))
return;
int carry = 0;
if ((l1->next == NULL) && (l2->next != NULL)) {
carry += listadd (l1, l2->next) + l2->val;
return carry;
}
else if ((l1->next != NULL) && (l2->next == NULL)) {
carry +=listadd (l1->next, l2);
l1->val = l1->val + carry;
}
else if ((l1->next != NULL) && (l2->next != NULL)) {
carry += listadd (l1->next, l2->next);
}
else if ((l1->next == NULL) && (l2->next == NULL)) {
l1->val = l1->val + l2->val;
carry = l1->val/10;
l1->val = l1->val%10;
return carry;
}
carry = l1->val/10;
l1->val = l1->val%10;
return carry;
}
struct list * createnode (int val) {
struct list * temp = (struct list *) malloc (sizeof(struct list));
temp->val = val;
temp->next = NULL;
return temp;
}
int main() {
int carry = 0;
struct list *l1 = createnode(1);
l1->next = createnode(2);
struct list *l2 = createnode(7);
l2->next = createnode(8);
carry = listadd(l1,l2);
if (carry != 0) {
struct list * temp = createnode(carry);
temp->next = l1;
l1 = temp;
}
while (l1!= NULL) {
printf ("%d", l1->val);
l1=l1->next;
}
}

Resources