I was trying simple stack implementation in C. Here is my simple code:
1 #include "stdio.h"
2 #include "limits.h"
3 #include "malloc.h"
4
5 typedef struct StackEntry StackEntry;
6
7 struct StackEntry
8 {
9 int data;
10 StackEntry *next;
11 };
12
13 StackEntry* createStack(){
14 return NULL;
15 }
16
17 int isEmptyStack(StackEntry **pStackTop)
18 {
19 return *pStackTop == NULL;
20 }
21
22 void push(StackEntry **pStackTop, int pData)
23 {
24 StackEntry *lTempStackEntry;
25 lTempStackEntry = (StackEntry*)malloc(sizeof(StackEntry));
26
27 if(!lTempStackEntry)
28 return;
29
30 lTempStackEntry->data = pData;
31 lTempStackEntry->next = *pStackTop;
32
33 *pStackTop = lTempStackEntry;
34 }
35
36 int pop(StackEntry **pStackTop)
37 {
38 int lTempData;
39 StackEntry *lTempStackEntry;
40
41 if(isEmptyStack(pStackTop))
42 return INT_MIN;
43
44 lTempStackEntry = *pStackTop;
45 *pStackTop = (*pStackTop)->next;
46 lTempData = lTempStackEntry->data;
47 free(lTempStackEntry);
48
49 return lTempData;
50 }
51
52 int stackTop(StackEntry **pStackTop)
53 {
54 if(isEmptyStack(pStackTop))
55 return INT_MIN;
56
57 return (*pStackTop)->data;
58 }
59
60 void deleteStack(StackEntry ** pStackTop)
61 {
62 StackEntry *secondTopNode, *topNode;
63 topNode = *pStackTop;
64 /*
65 * In this we free all the nodes from second top to bottom,
66 * by one by one attaching them to top->next. At the end
67 * we free the top node.
68 */
69 while(topNode->next)
70 {
71 secondTopNode = topNode->next;
72 topNode->next = secondTopNode->next; //make third top node
73 //second top node
74 free(secondTopNode);
75 secondTopNode = NULL;
76 }
77 free(topNode);
78 topNode = NULL;
79 }
80
81 int main(void) {
82 // your code goes here
83 StackEntry *stack = createStack(); //stack: 0x0
84 printf("\n push 1");
85 push(&stack,1);
86 printf("\n push 2");
87 push(&stack,2);
88 printf("\n push 3");
89 push(&stack,3);
90 printf("\n stack top: %d", stackTop(&stack));
91 printf("\n pop: %d ",pop(&stack));
92 printf("\n stack top: %d", stackTop(&stack));
93 printf("\n pop: %d ",pop(&stack));
94 printf("\n stack top: %d", stackTop(&stack));
95
96 deleteStack(&stack);
97 printf("\n stack deleted.");
98 printf("\n is stack empty: %d", isEmptyStack(&stack)); //here it should print 1, but its printing 0
99
100 printf("\n push 1");
101 push(&stack,1);
102 printf("\n push 2");
103 push(&stack,2);
104
105 printf("\n pop: %d ",pop(&stack));
106 printf("\n pop: %d ",pop(&stack));
107 return 0;
108 }
Output
push 1
push 2
push 3
stack top: 3
pop: 3
stack top: 2
pop: 2
stack top: 1
stack deleted.
is stack empty: 0
push 1
push 2
pop: 2
pop: 1
In deleteStack(), I free up all of the stack entry and set stack top to NULL. In isEmptyStack() check if the stack top is empty. So it should evaluate to 1 and line 98 should print 1 (i.e. true), but it prints 0.
Whats wrong here? Here is the code on ideone.
Debugging efforts I took:
In function deleteStack, you don't set stack to null instead a copy of stack pointer to null.
What you do is:
topNode = *pStackTop;
topNode = NULL;
Which is incorrect.
What you should instead do is:
*pStackTop = NULL;
Related
I try to make linked list for string and sort with their score but my sorting algorithm is doing nothing. Thank you for any advice and help.
void SortList(Linked_List *list) {
Node *temp, *index = NULL;
temp = list->head;
int tmp;
if (list->head == NULL) {
return;
} else {
while (temp != NULL) {
index = temp->next;
while (index != NULL) {
if (temp->score > index->score) {
tmp = temp->score;
temp->score = index->score;
index->score = tmp;
}
index = index->next;
}
temp = temp->next;
}
}
}
here are my structure definitions:
typedef struct Node {
void *data;
int score;
struct Node *next;
} Node;
typedef struct {
Node *head;
} Linked_List;
here is my main method(i removed first 2 cases because they are not related to my problem):
int main()
{
FILE *fp,*fp2,*fp3;
int bufferLength = 99;
char line[RSIZ][LSIZ];
char str[RSIZ][LSIZ];
int k,point=0;
Linked_List* char_list = create_empty_list();
char buffer[bufferLength];
char password[99];
int counter=0,len1=0,len2=0,choice,i=0,tot=0,j;
bool quit = false;
and here is swtich case method:
while(!quit){
printf("\t\t\t3.LinkedList:\n");
printf("\t\t\tAny other to exit():\n");
scanf("%d",&choice);
switch(choice){
case 3:
fp3 = fopen("10-million-password-list-top/1000.txt","r");
if(fp3==NULL){
printf("Could not open the file\n");
}
while(fgets(str[k],LSIZ,fp3)){
str[k][strlen(str[k])-1]= '\0';
Linked_List* char_list = create_empty_list();
char_list->head = insert_end(char_list, str[k]);
calculating password strength it is longer than this one i removed it is unnecessary detail for this problem.
int j;
for(j=0;str[k][j]!=0;j++){
if(str[k][j]>=97 && str[k][j]<=122){ //lowercase
point+=3;
}
else if(str[k][j]>=48 && str[k][j]<=57){ //digits
point+=10;
}}
Scoring(char_list,point);
point=0;
k++;
SortList(char_list);
display(char_list);
printf("\n");
}break;
default:
quit=true;
break;
}}
free_list(char_list);
fclose(fp2);
return 0;
}
You're swapping the data in the nodes, instead of the link pointers.
While you can do this, normally, only the link pointers get swapped. Suppose your struct had (in addition), something like: int array[1000000]; as an element. You'd have to swap that and that would be very slow compared to just changing pointers.
And, you only doing one pass on the data. So, you might get the lowest value at the front of the list, but all the others will remain unsorted.
That is, for a list with N elements, and simple sorts (with O(N^2) complexity), you need N passes.
I had to refactor your code a bit.
The algorithm I came up with is to have a temporary "destination" list [initially empty].
For each pass, the original list is scanned for the smallest/lowest element.
That element is removed from the source list and appended to the destination list.
At the end, the address of the head of the temp list is copied into the original list's head element.
Anyway, here is the code. I tried to annotate it as much as possible. It compiles cleanly and I've desk checked it for correctness. But, I didn't test it, so it may have some bugs. But, it should get you started.
#include <stdio.h>
typedef struct Node {
void *data;
int score;
struct Node *next;
} Node;
typedef struct {
Node *head;
} Linked_List;
void
SortList(Linked_List *srclist)
{
Node *dsthead = NULL;
Node *dstprev = NULL;
// do N passes on the list
while (1) {
// get next element in source list -- stop when empty
Node *srcbest = srclist->head;
if (srcbest == NULL)
break;
// find smallest node in remaining list
Node *bestprev = NULL;
Node *curprev = NULL;
for (Node *cursrc = srcbest; cursrc != NULL; cursrc = cursrc->next) {
if (cursrc->score < srcbest->score) {
srcbest = cursrc;
bestprev = curprev;
}
curprev = cursrc;
}
// add selected node to tail of destination list
if (dsthead == NULL)
dsthead = srcbest;
else
dstprev->next = srcbest;
dstprev = srcbest;
// remove selected node from source list
if (bestprev != NULL)
bestprev->next = srcbest->next;
else
srclist->head = srcbest->next;
// fix the tail of destination list
dstprev->next = NULL;
}
// set new head of original list
srclist->head = dsthead;
}
UPDATE:
i tried this one also but still does not sort gives me same linked list.
Since my original post, I created a test program. The algorithm works [as posted]. So, there must be something else within your code.
The algorithm was similar to an insertion sort. I added a bubble sort variant.
Here's the full working code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node {
void *data;
int score;
struct Node *next;
} Node;
typedef struct {
Node *head;
Node *tail;
int count;
} Linked_List;
#define DOTEST(_fnc,_count) \
dotest(_fnc,#_fnc,_count)
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
enum {
OPT_SWAPFLG = 1u << 0,
OPT_SHORTEN = 1u << 1,
};
double tsczero;
double
tscgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_MONOTONIC,&ts);
sec = ts.tv_nsec;
sec /= 1e9;
sec += ts.tv_sec;
sec -= tsczero;
return sec;
}
int
show(Node *cur)
{
int score;
if (cur != NULL)
score = cur->score;
else
score = -1;
return score;
}
// SortList -- insertion sort
void
SortList(Linked_List *srclist)
{
Node *dsthead = NULL;
Node *dstprev = NULL;
// do N passes on the list
while (1) {
// get next element in source list -- stop when empty
Node *srcbest = srclist->head;
if (srcbest == NULL)
break;
// find smallest node in remaining list
Node *bestprev = NULL;
Node *curprev = NULL;
for (Node *cursrc = srcbest; cursrc != NULL; cursrc = cursrc->next) {
if (cursrc->score < srcbest->score) {
srcbest = cursrc;
bestprev = curprev;
}
curprev = cursrc;
}
// add selected node to tail of destination list
if (dsthead == NULL)
dsthead = srcbest;
else
dstprev->next = srcbest;
dstprev = srcbest;
// remove selected node from source list
if (bestprev != NULL)
bestprev->next = srcbest->next;
else
srclist->head = srcbest->next;
// fix the tail of destination list
dstprev->next = NULL;
}
// set new head of original list
srclist->head = dsthead;
}
// SwapCom -- bubble sort
void
SwapCom(Linked_List *list,unsigned int opt)
{
Node *dsthead = NULL;
Node *dstprev = NULL;
Node *tail = NULL;
int swapflg = 1;
// do N passes on the list -- stop early if list becomes sorted
while (swapflg) {
if (opt & OPT_SWAPFLG)
swapflg = 0;
Node *prev = list->head;
if (prev == NULL)
break;
dbgprt("SwapList: START\n");
Node *next;
Node *pprev = NULL;
for (Node *cur = prev->next; cur != NULL; cur = next) {
next = cur->next;
dbgprt("SwapCom: CUR head=%d pprev=%d prev=%d cur=%d next=%d\n",
show(list->head),show(pprev),show(prev),show(cur),show(next));
// last element is always in sort
if (cur == tail) {
dbgprt("SwapCom: SHORT\n");
break;
}
// the two elements are already in order
if (prev->score <= cur->score) {
pprev = prev;
prev = cur;
continue;
}
// say we had to swap -- we require another pass
dbgprt("SwapCom: SWAP\n");
swapflg = 1;
// adjust the head of the list
if (prev == list->head)
list->head = cur;
// swap the link pointers
cur->next = prev;
prev->next = next;
// adjust previous
if (pprev != NULL)
pprev->next = cur;
//next = prev;
pprev = cur;
//prev = cur;
}
if (opt & OPT_SHORTEN)
tail = prev;
}
}
// SwapEarly -- bubble sort
void
SwapEarly(Linked_List *list)
{
SwapCom(list,OPT_SWAPFLG);
}
// SwapShort -- bubble sort
void
SwapShort(Linked_List *list)
{
SwapCom(list,OPT_SWAPFLG | OPT_SHORTEN);
}
void
split(Linked_List *list,Linked_List *listl,Linked_List *listr)
{
int c2 = list->count / 2;
int idx = 1;
Node *rhs;
// find the midpoint
for (rhs = list->head; rhs != NULL; rhs = rhs->next, ++idx) {
if (idx >= c2)
break;
}
listl->head = list->head;
listl->count = c2;
listr->count = list->count - c2;
listr->head = rhs->next;
rhs->next = NULL;
}
void
merge(Linked_List *list,Linked_List *listl,Linked_List *listr)
{
Node *lhs = listl->head;
Node *rhs = listr->head;
Node *prev;
Node *cur;
list->head = NULL;
list->count = 0;
prev = NULL;
while ((lhs != NULL) && (rhs != NULL)) {
if (lhs->score <= rhs->score) {
cur = lhs;
lhs = lhs->next;
listl->count -= 1;
}
else {
cur = rhs;
rhs = rhs->next;
listr->count -= 1;
}
if (prev != NULL)
prev->next = cur;
else
list->head = cur;
list->count += 1;
prev = cur;
prev->next = NULL;
}
if (lhs != NULL) {
list->count += listl->count;
prev->next = lhs;
}
if (rhs != NULL) {
list->count += listr->count;
prev->next = rhs;
}
}
void
mergesort(Linked_List *list)
{
Linked_List listl;
Linked_List listr;
if (list->count >= 2) {
split(list,&listl,&listr);
mergesort(&listl);
mergesort(&listr);
merge(list,&listl,&listr);
}
}
// MergeSort -- merge sort
void
MergeSort(Linked_List *list)
{
mergesort(list);
}
Linked_List *
newlist(int count)
{
Linked_List *list = calloc(1,sizeof(*list));
Node *prev = NULL;
for (int idx = 1; idx <= count; ++idx) {
Node *cur = calloc(1,sizeof(*cur));
cur->score = count - idx;
if (prev != NULL)
prev->next = cur;
else
list->head = cur;
list->tail = cur;
list->count += 1;
prev = cur;
}
return list;
}
void
freelist(Linked_List *list)
{
Node *next;
for (Node *cur = list->head; cur != NULL; cur = next) {
next = cur->next;
free(cur);
}
free(list);
}
int
chklist(Linked_List *list)
{
Node *prev = list->head;
Node *cur;
int idx = 0;
int err = 0;
if (prev != NULL)
cur = prev->next;
else
cur = NULL;
for (; cur != NULL; cur = cur->next, ++idx) {
if (prev->score > cur->score) {
printf("chklist: ERROR index %d -- prev=%d cur=%d\n",idx,prev,cur);
if (++err > 10)
break;
}
prev = cur;
}
if (err)
exit(1);
// get the count
idx += 1;
return idx;
}
void
prtlist(Linked_List *list,const char *reason)
{
int totlen = 0;
totlen += printf("%s:",reason);
for (Node *cur = list->head; cur != NULL; cur = cur->next) {
totlen += printf(" %d",cur->score);
if (totlen >= 70) {
printf("\n");
totlen = 0;
}
}
if (totlen > 0)
printf("\n");
}
void
dotest(void (*sort)(Linked_List *),const char *reason,int count)
{
Linked_List *list;
int prtflg = (count <= 100);
printf("\n");
printf("Testing %s for %d elements ...\n",reason,count);
list = newlist(count);
if (prtflg)
prtlist(list,"Unsorted");
double tscbeg = tscgetf();
sort(list);
double tscend = tscgetf();
tscend -= tscbeg;
if (prtflg)
prtlist(list,"Sorted");
int chk = chklist(list);
if (chk != count) {
printf("dotest: check count mismatch -- expected: %d actual: %d\n",
count,chk);
exit(1);
}
freelist(list);
double rate;
#if 0
rate = count;
rate /= tscend;
#else
rate = tscend;
rate /= count;
#endif
printf("ELAPSED: %.9f RATE: %.9f\n",tscend,rate);
fflush(stdout);
}
int
main(void)
{
int counts[] = { 10, 100, 1000, 10000, 100000, -1 };
tsczero = tscgetf();
for (int idx = 0; ; ++idx) {
int count = counts[idx];
if (count < 0)
break;
printf("\n");
for (int idx = 0; idx <= 70; ++idx)
printf("-");
printf("\n");
DOTEST(SortList,count);
DOTEST(SwapEarly,count);
DOTEST(SwapShort,count);
DOTEST(MergeSort,count);
}
return 0;
}
Here's the program output:
-----------------------------------------------------------------------
Testing SortList for 10 elements ...
Unsorted: 9 8 7 6 5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9
ELAPSED: 0.000000696 RATE: 0.000000070
Testing SwapEarly for 10 elements ...
Unsorted: 9 8 7 6 5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9
ELAPSED: 0.000001120 RATE: 0.000000112
Testing SwapShort for 10 elements ...
Unsorted: 9 8 7 6 5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9
ELAPSED: 0.000000696 RATE: 0.000000070
Testing MergeSort for 10 elements ...
Unsorted: 9 8 7 6 5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9
ELAPSED: 0.000000835 RATE: 0.000000083
-----------------------------------------------------------------------
Testing SortList for 100 elements ...
Unsorted: 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79
78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55
54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99
ELAPSED: 0.000031237 RATE: 0.000000312
Testing SwapEarly for 100 elements ...
Unsorted: 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79
78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55
54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99
ELAPSED: 0.000083257 RATE: 0.000000833
Testing SwapShort for 100 elements ...
Unsorted: 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79
78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55
54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99
ELAPSED: 0.000045619 RATE: 0.000000456
Testing MergeSort for 100 elements ...
Unsorted: 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79
78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55
54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
5 4 3 2 1 0
Sorted: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99
ELAPSED: 0.000007023 RATE: 0.000000070
-----------------------------------------------------------------------
Testing SortList for 1000 elements ...
ELAPSED: 0.003071345 RATE: 0.000003071
Testing SwapEarly for 1000 elements ...
ELAPSED: 0.008256265 RATE: 0.000008256
Testing SwapShort for 1000 elements ...
ELAPSED: 0.004658966 RATE: 0.000004659
Testing MergeSort for 1000 elements ...
ELAPSED: 0.000110933 RATE: 0.000000111
-----------------------------------------------------------------------
Testing SortList for 10000 elements ...
ELAPSED: 0.312265008 RATE: 0.000031227
Testing SwapEarly for 10000 elements ...
ELAPSED: 0.829503246 RATE: 0.000082950
Testing SwapShort for 10000 elements ...
ELAPSED: 0.450563461 RATE: 0.000045056
Testing MergeSort for 10000 elements ...
ELAPSED: 0.001036259 RATE: 0.000000104
-----------------------------------------------------------------------
Testing SortList for 100000 elements ...
ELAPSED: 31.850022147 RATE: 0.000318500
Testing SwapEarly for 100000 elements ...
ELAPSED: 84.817288841 RATE: 0.000848173
Testing SwapShort for 100000 elements ...
ELAPSED: 46.089681707 RATE: 0.000460897
Testing MergeSort for 100000 elements ...
ELAPSED: 0.012533725 RATE: 0.000000125
UPDATE #2:
Just for fun, I've edited the second code block to include a mergesort [and updated the program output block].
i tested with your last sorting algorithm too but still werent sorted. – Chuck
For smaller numbers, my test program prints out the list after sorting. You can visually inspect the before and after.
Chuck Obviously you don't know how to test whether a list is sorted. Show us the code that lets you determine whether the list is sorted or not. – Kuba hasn't forgotten Monica
My test program had a [simple] test for the list being in sort or not, and would have aborted if the list were not sorted.
You can compare your sort check code to my chklist code.
However ...
In the code you posted in your recent update, the code that reads in lines from the file is broken. I've annotated and fixed this code:
// and this one is my main for reading from txt file:
fp3 = fopen("10-million-password-list-top/aa.txt", "r");
if (fp3 == NULL) {
printf("Could not open the file\n");
}
#if 0
// NOTE/BUG: why have str be an array of pointers?
while (fgets(str[k], LSIZ, fp3)) {
str[k][strlen(str[k]) - 1] = '\0';
// NOTE/BUG: this _destroys_ the list on each iteration
Linked_List *char_list = create_empty_list();
// NOTE/BUG: insert_end _modifies_ list->head _directly_ -- no need to return
// the head value
char_list->head = insert_end(char_list, str[k]);
}
#else
char linebuf[1000];
Linked_List *char_list = create_empty_list();
while (fgets(linebuf,sizeof(linebuf),fp3)) {
linebuf[strlen(linebuf) - 1] = 0;
insert_end(char_list,linebuf);
}
#endif
The insert_end code is also broken:
// NOTE/BUG: list->head is updated internally -- no need to return it
#if 0
Node *
insert_end(Linked_List *list, void *data)
#else
void
insert_end(Linked_List *list, const char *data)
#endif
{
Node *new_node;
Node *temp;
// NOTE/BUG: don't cast the return value of malloc
#if 0
new_node = (Node *) malloc(sizeof(Node));
#else
new_node = malloc(sizeof(*new_node));
#endif
// NOTE/BUG: this is _not_ the way to allocate space for the string
// NOTE/BUG: the next line blows away the value just obtained from malloc
#if 0
new_node->data = malloc(sizeof(char *));
new_node->data = (char *) data;
#else
new_node->data = strdup(data);
#endif
new_node->next = NULL;
if (list->head == NULL) {
list->head = new_node;
}
else {
temp = list->head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = new_node;
}
#if 0
return (list->head);
#endif
}
The program is supposed to swap neighbouring elements which don't have a common denominator, and an element can only be swapped once.
When i run the program, pretty much for any input works fine. Except for this one:
100 //input for number of elements
48 92 76 93 17 38 59 34 53 99 58 20 50 0 38 37 16 36 91 12 59 1 76 82 20 76 7 72 13 70 64 23 81 70 41 69 11 0 16 41 37 83 41 99 73 79 4 38 24 32 87 38 95 24 77 30 61 13 89 67 87 76 22 31 67 31 25 90 6 76 21 43 40 55 72 91 91 28 18 58 72 71 83 22 99 23 86 58 75 53 69 29 5 55 46 8 98 55 19 46 //the elements
For this input, the program hangs and prints nothing. Does someone know what is going on in this particular case?
#include <stdio.h>
int nzd(int a, int b)
{
if(a==b || b==0)
return a;
if(a>b)
return nzd(a-b, b);
return nzd(a, b-a);
}
int swap(int *niza, int i)
{
int temp;
temp=*(niza+i);
*(niza+i)=*(niza+i+1);
*(niza+i+1)=temp;
}
int main()
{
int a[100], n, i;
scanf("%d", &n);
for(i=0; i<n; i++)
{
scanf("%d", &a[i]);
}
for(i=0; i<n; i++)
{
if(i+1==n) continue;
if(nzd(a[i], a[i+1])==1)
{
swap(a, i);
i++;
}
}
for(i=0; i<n; i++)
{
printf("%d ", a[i]);
}
return 0;
}
Your gcd function checks for the case of b==0 but not the case for a==0. Because you skip that check, you end up calling nzd(0, b-0); which is exactly the same as the prior call. This puts you in an infinite recursion loop which will eventually cause a stack overflow.
Add the check for this case in your function:
if(a==b || b==0 || a == 0)
Also, a faster implementation of gcd, called Euclid's algorithm, is as follows:
int gcd(int a, int b)
{
if (b==0) {
return a;
} else {
return (b, a%b);
}
}
Your function nzd() fails to handle the case a == 0 correctly and gets stuck in an endless loop. You need to handle this case, too:
int nzd(int a, int b)
{
if(a==b || a==0 || b==0)
return a;
if(a>b)
return nzd(a-b, b);
return nzd(a, b-a);
}
What's wrong with this code?
My task is: Create a square matrix of integers with a size of 9x9. Fill the matrix with random numbers. Display the main and side diagonal symmetrically with respect to the vertical axis. The example of expected result is here: matrix
Matrix :
20 20 76 65 93 76 16 2 85
6 87 78 43 48 81 71 90 38
10 12 35 77 48 88 24 53 7
12 66 51 35 74 7 30 22 49
58 14 71 46 68 68 10 81 51
98 16 74 47 64 25 17 30 37
2 44 44 74 34 54 86 73 28
85 4 57 75 18 28 51 76 2
35 17 53 76 15 91 83 85 72
The main and side diagonal:
85 20 76 65 93 76 16 2 20
6 90 78 43 48 81 71 87 38
10 12 24 77 48 88 35 53 7
12 66 51 7 74 35 30 22 49
58 14 71 46 68 68 10 81 51
98 16 74 25 64 47 17 30 37
2 44 86 74 34 54 44 73 28
85 76 57 75 18 29 51 4 2
72 17 53 76 15 91 83 85 35
But in fact the program prints only the main matrix with random numbers and after that stops.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <Windows.h>
int main()
{
int a = 9;
int matrix[a][a];
int temp;
int i, j, n;
srand((unsigned)time(NULL));
printf("Matrix : \n\n");
for (i = 0; i < a; ++i) {
for (j = 0; j < a; ++j) {
matrix[i][j] = rand() % 100;
printf("%d\t", matrix[i][j]);
}
printf("\n\n");
}
printf("The main and side diagonal:\n\n");
for (i = 0; i < a; ++i) {
temp = matrix[i][i];
matrix[i][i] = matrix[i][(a - 1) - i];
matrix[i][(a - 1) - i] = temp;
}
for (i = 0; i < a; ++i) {
for (j = 0; j < a; ++j) {
printf("Result:", matrix[i][j]);
printf("\n\n\n");
system("pause");
return 0;
}
}
}
You are returning where you are not supposed to. (in middle of the calculation). You should return after you end up working on the for loops.
for (i = 0; i < a; ++i) {
for (j = 0; j < a; ++j) {
printf("Result:", matrix[i][j]); <--- Not printing element
printf("\n\n\n");
system("pause");
return 0; <-----
}
}
It should be
for (i = 0; i < a; ++i) {
for (j = 0; j < a; ++j) {
printf("Result: %d ", matrix[i][j]); <----You forgot the
//format specifier
printf("\n\n\n");
system("pause");
}
}
return 0;<-----
Readability is hampered when the indentation is like this. You implemented wrong logic out of it.
OP asks that it stops after printing "Result" that is because you forgot to put the format specifier in the code. That's why none of the element is printed.
Op wants to print the main and side diagonal symmetrically with respect to the vertical axis.
Now this is everything to with the print part.
Now we have to find a way that will let us distinguish which one is diagonal element and which one is not.
Suprisingly the answer should be known to someone who is writing the previous swapping logic. (Though it is not clear why OP swapped it).
Now all element matrix[p][q] will be from either diagonal if p=q or p+q=a-1. (Note that matrix is a square matrix).
But OP meant to print the matrix
for (i = 0; i < a; ++i) {
if( i == 0) printf("The main and side diagonal : \n");
for (j = 0; j < a; ++j) {
printf("%d\t", matrix[i][j]);
}
printf("\n");
}
}
Use functions. You print the matrix twice; you should have a function to print the matrix which you call twice.
With such a function, you'd not make the mistakes in the tail end of your code. For example, you could use this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static void print_matrix(const char *tag, int size, int matrix[size][size])
{
printf("%s (%dx%d):\n\n", tag, size, size);
for (int i = 0; i < size; ++i)
{
const char *pad = "";
for (int j = 0; j < size; ++j)
{
printf("%s%-2d", pad, matrix[i][j]);
pad = " ";
}
printf("\n\n");
}
}
int main(int argc, char **argv)
{
unsigned seed = time(0);
int a = 9;
int matrix[a][a];
if (argc == 2)
seed = atoi(argv[1]);
srand(seed);
printf("Seed: %u\n", seed);
for (int i = 0; i < a; ++i)
{
for (int j = 0; j < a; ++j)
matrix[i][j] = rand() % 100;
}
print_matrix("Matrix", a, matrix);
for (int i = 0, j = a - 1; i < a; ++i, --j)
{
int temp = matrix[i][i];
matrix[i][i] = matrix[i][j];
matrix[i][j] = temp;
}
print_matrix("The main and side diagonal", a, matrix);
return 0;
}
The code reports the seed it uses; that allows you to reproduce any run by specifying the seed to use as a command line argument.
Example output:
Seed: 1511470282
Matrix (9x9):
11 39 3 88 98 63 75 81 76
93 9 60 22 45 50 46 58 65
13 99 25 43 14 57 44 70 65
30 57 55 0 37 84 47 49 40
60 28 46 1 96 78 33 20 9
93 61 11 38 84 16 91 26 15
43 85 66 72 85 39 96 45 45
45 25 33 3 78 90 61 65 62
88 84 56 34 74 8 78 57 74
The main and side diagonal (9x9):
76 39 3 88 98 63 75 81 11
93 58 60 22 45 50 46 9 65
13 99 44 43 14 57 25 70 65
30 57 55 84 37 0 47 49 40
60 28 46 1 96 78 33 20 9
93 61 11 16 84 38 91 26 15
43 85 96 72 85 39 66 45 45
45 65 33 3 78 90 61 25 62
74 84 56 34 74 8 78 57 88
The swapping process, in case it isn't obvious, swaps the first and last elements of the first row, the second and last but one element in the second row, and so on, forming an X of swapped elements.
This is what i have so far. I really don't understand where i went wrong. It needs to print after it has visited the left most node and then right then print.
void printPostOrderIterative(BSTNode *root)
{
BSTNode *cur;
Stack s;
s.top = NULL;
Stack output;
output.top = NULL;
if (!root) {
return;
}
push(&s, root);
while (isEmpty(&s) != 1 ) {
cur = s.top;
push(&output,cur);
pop(&s);
if (cur->left){
push(&s, cur->left);
}
if (cur->right){
push(&s, cur->right);
}
}
while (isEmpty(&output) != 1) {
printf("%d", output.top);
pop(&output);
}
}
Currently, the code just keeps looping in the first while loop.
Here is some working code. I had to implement an approximation to your stack code, and the BST code, but I made only very simple changes to your function. There are arguments that I should not have had to do the creation: Stack Overflow encourages you to create an MCVE (How to create a Minimal, Complete, and Verifiable Example?)
SSCCE (Short, Self-Contained, Correct Example) — two names and links for the same basic idea.
Without any major algorithmic tweaks, your code (a) completes and (b) produces the same answer as a recursive post-order print function (on one sample data set).
static void printPostOrderIterative(BSTNode *root)
{
if (!root) // Moved to avoid stack initialization before returning
return; // …ditto…
Stack s;
Stack output;
init(&s); // Different initialization
init(&output); // Different initialization
push(&s, root);
while (isEmpty(&s) != 1)
{
BSTNode *cur = top(&s); // Different code
push(&output, cur);
pop(&s);
if (cur->left)
push(&s, cur->left);
if (cur->right)
push(&s, cur->right);
}
while (isEmpty(&output) != 1)
{
BSTNode *c = top(&output); // Different code
printf(" %d", c->data); // Added space
pop(&output);
}
putchar('\n'); // Extra code
clean(&s); // Extra code
clean(&output); // Extra code
}
Thus the problem is probably not in the code you show — it is more likely in the code you don't show. My best guess is that the stack implementation is slightly faulty, but since you don't show it, it is hard to be sure.
Full code
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct BSTNode BSTNode;
struct BSTNode
{
int data;
BSTNode *left;
BSTNode *right;
};
typedef struct Stack
{
size_t size;
size_t top;
BSTNode **stack;
} Stack;
static void err_syserr(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
exit(1);
}
static void push(Stack *sp, BSTNode *np)
{
assert(sp != 0 && np != 0);
if (sp->top == sp->size)
{
size_t n_size = (sp->size + 2) * 2;
void *n_data = realloc(sp->stack, n_size * sizeof(*sp->stack));
if (n_data == 0)
err_syserr("Out of memory (%zu bytes requested)\n",
n_size * sizeof(*sp->stack));
sp->stack = n_data;
sp->size = n_size;
}
sp->stack[sp->top++] = np;
}
static bool isEmpty(Stack *sp)
{
return sp->top == 0;
}
static void pop(Stack *sp)
{
if (!isEmpty(sp))
sp->top--;
}
static void init(Stack *sp)
{
sp->top = 0;
sp->size = 0;
sp->stack = 0;
}
static BSTNode *top(Stack *sp)
{
if (sp->top == 0)
return 0;
return sp->stack[sp->top - 1];
}
static void clean(Stack *sp)
{
while (sp->top > 0)
free(sp->stack[--sp->top]);
free(sp->stack);
init(sp);
}
static BSTNode *new_node(int data)
{
BSTNode *np = malloc(sizeof(*np));
if (np == 0)
err_syserr("Out of memory (%zu bytes requested)\n", sizeof(*np));
np->data = data;
np->left = 0;
np->right = 0;
return np;
}
static void printPostOrderIterative(BSTNode *root)
{
if (!root)
return;
Stack s;
Stack output;
init(&s); // Different initialization
init(&output); // Different initialization
push(&s, root);
while (isEmpty(&s) != 1)
{
BSTNode *cur = top(&s); // Different code
push(&output, cur);
pop(&s);
if (cur->left)
push(&s, cur->left);
if (cur->right)
push(&s, cur->right);
}
while (isEmpty(&output) != 1)
{
BSTNode *c = top(&output);
printf(" %d", c->data);
pop(&output);
}
putchar('\n'); // Extra code
clean(&s); // Extra code
clean(&output); // Extra code
}
static void printPostOrderRecursive(BSTNode *root)
{
if (root != 0)
{
printPostOrderRecursive(root->left);
printPostOrderRecursive(root->right);
printf(" %d", root->data);
}
}
static void printInOrderRecursive(BSTNode *root)
{
if (root != 0)
{
printInOrderRecursive(root->left);
printf(" %d", root->data);
printInOrderRecursive(root->right);
}
}
static BSTNode *bst_add(BSTNode *root, int data)
{
if (root == 0)
root = new_node(data);
else if (root->data > data)
root->left = bst_add(root->left, data);
else
root->right = bst_add(root->right, data);
return root;
}
static void bst_destroy(BSTNode *root)
{
if (root != 0)
{
bst_destroy(root->left);
bst_destroy(root->right);
free(root);
}
}
int main(void)
{
int data[] =
{
71, 57, 4, 31, 47, 65, 69, 65, 98, 81,
54, 58, 17, 37, 48, 64, 64, 93, 40, 22,
45, 62, 99, 47, 18, 86, 67, 99, 68, 27,
};
enum { NUM_DATA = sizeof(data) / sizeof(data[0]) };
BSTNode *root = 0;
for (int i = 0; i < NUM_DATA; i++)
{
root = bst_add(root, data[i]);
printInOrderRecursive(root);
putchar('\n');
}
printPostOrderRecursive(root);
putchar('\n');
printPostOrderIterative(root);
bst_destroy(root);
return 0;
}
Sample output
71
57 71
4 57 71
4 31 57 71
4 31 47 57 71
4 31 47 57 65 71
4 31 47 57 65 69 71
4 31 47 57 65 65 69 71
4 31 47 57 65 65 69 71 98
4 31 47 57 65 65 69 71 81 98
4 31 47 54 57 65 65 69 71 81 98
4 31 47 54 57 58 65 65 69 71 81 98
4 17 31 47 54 57 58 65 65 69 71 81 98
4 17 31 37 47 54 57 58 65 65 69 71 81 98
4 17 31 37 47 48 54 57 58 65 65 69 71 81 98
4 17 31 37 47 48 54 57 58 64 65 65 69 71 81 98
4 17 31 37 47 48 54 57 58 64 64 65 65 69 71 81 98
4 17 31 37 47 48 54 57 58 64 64 65 65 69 71 81 93 98
4 17 31 37 40 47 48 54 57 58 64 64 65 65 69 71 81 93 98
4 17 22 31 37 40 47 48 54 57 58 64 64 65 65 69 71 81 93 98
4 17 22 31 37 40 45 47 48 54 57 58 64 64 65 65 69 71 81 93 98
4 17 22 31 37 40 45 47 48 54 57 58 62 64 64 65 65 69 71 81 93 98
4 17 22 31 37 40 45 47 48 54 57 58 62 64 64 65 65 69 71 81 93 98 99
4 17 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 69 71 81 93 98 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 69 71 81 93 98 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 69 71 81 86 93 98 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 67 69 71 81 86 93 98 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 67 69 71 81 86 93 98 99 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 67 68 69 71 81 86 93 98 99 99
4 17 18 22 27 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 67 68 69 71 81 86 93 98 99 99
18 27 22 17 45 40 37 47 48 54 47 31 4 62 64 64 58 68 67 65 69 65 57 86 93 81 99 99 98 71
18 27 22 17 45 40 37 47 48 54 47 31 4 62 64 64 58 68 67 65 69 65 57 86 93 81 99 99 98 71
Discussion
Since you used interleaved declarations and statement, you're using at least C99 so I've used <stdbool.h> and bool type. This code compiles cleanly, at least when compiled with the options (Mac OS X 10.11.4, GCC 5.3.0):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
> -Wold-style-definition -Werror nr-post.c -o nr-post
$
The code runs cleanly under valgrind (3.12.0-SVN).
The first lines of output are printed in-order as the tree is built up (from 30 integers from the range 0..99 generated at random). This allows me to see that the tree is built correctly from the ground up. The last two lines of output are first from printPostOrderRecursive(), a simple recursive implementation of post-order printing, and then from (my mild adaptation of your) printPostOrderIterative().
Without your stack implementation available, I have to guess that you have a problem somewhere in there. With a straight-forward implementation of a stack as shown (where the top is an index into the array of node pointers), your code is fine. We can't tell whether you have compilation warnings you're ignoring.
Hmmm, reviewing my code, I see it doesn't check that top() returns a non-null pointer. It's tempting to add an assertion, and a run-time error rather than returning null. There are plenty of other assertions that could be added — non-null stack pointers passed to the stack functions, in particular.
I'm trying to do a partial sort with a threads,
my current output it
27 12 21 48 15 28 82 69 35 91
13 82 33 35 46 5 35 28 87 95
0 10 20 22 23 30 52 80 86 96
3 8 42 53 67 70 70 71 75 79
5 8 8 18 41 43 70 79 86 88
10 51 56 60 65 84 87 91 94 99
23 25 38 39 40 44 51 56 69 75
20 21 25 29 29 38 66 71 73 96
33 50 9 6 13 27 97 21 70 22
3 4 6 6 7 15 34 59 63 70
As you can see I am getting it partially sorted I want my output to be this (no merging at the end)
12 15 21 27 28 35 48 69 82 91
5 13 28 33 35 35 46 82 87 95
0 10 20 22 23 30 52 80 86 96
3 8 42 53 67 70 70 71 75 79
5 8 8 18 41 43 70 79 86 88
10 51 56 60 65 84 87 91 94 99
23 25 38 39 40 44 51 56 69 75
20 21 25 29 29 38 66 71 73 96
6 9 13 21 22 27 33 50 70 97
3 4 6 6 7 15 34 59 63 70
I can get the right output if instead of using a struct I use &array[i] and manually input the length
This is the code I have so far:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
int cmpfunc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
struct values {
int *arrayptr;
int length;
};
void *thread_fn(void *a) {
struct values *start = a;
qsort(start->arrayptr, start->length, sizeof(int), cmpfunc);
return (void*)a;
}
int main(int argc, const char *argv[]) {
FILE *fp = fopen(argv[3], "r");
FILE *fp1 = fopen("numS1.dat", "w+");
//amount of threads
int threadAmount = atoi(argv[1]);
//size of input
int numberAmount = atoi(argv[2]);
//multidimensional array
int array[threadAmount][numberAmount / threadAmount];
for (int i = 0; i < threadAmount; i++)
for (int j = 0; j < numberAmount / threadAmount; j++)
fscanf(fp, "%d", &array[i][j]);
pthread_t threadid[threadAmount];
for (int i = 0; i < threadAmount; ++i) {
struct values a = { array[i], numberAmount / threadAmount };
pthread_create(&threadid[i], NULL, thread_fn, &a);
}
for (int i = 0; i < threadAmount; ++i)
pthread_join(threadid[i], NULL);
for (int i = 0; i < threadAmount; i++) {
if (i != 0)
fprintf(fp1, "\n");
for (int j = 0; j < numberAmount / threadAmount; j++)
fprintf(fp1 ,"%d ", array[i][j]);
}
return 0;
}
Do you know where I am going wrong?
I think its the struct but everything I see online does what I'm doing.
You are passing a pointer to automatic storage to newly created threads: the struct values object becomes invalid as soon as the calling scope is exited, thus it cannot be reliably accessed by the new thread. You should allocate the struct values and pass the pointer to the allocated object as a parameter to pthread_create:
for (int i = 0; i < threadAmount; ++i) {
struct values *a = malloc(sizeof(*a));
a->arrayptr = array[i];
a->length = numberAmount / threadAmount;
pthread_create(&threadid[i], NULL, thread_fn, a);
}
The structure can be freed by the thread function before exiting.
Notes:
the way you split the array into chunks only works if the length is a multiple of the number of threads.
the comparison function does not work for large int values, you should use this instead:
int cmpfunc(const void *a, const void *b) {
return (*(int*)b < *(int*)a) - (*(int*)a < *(int*)b);
}