I'm working on a project about the N-queens game 8-puzzle for school and I'm encountering a problem for a week now. I have to implemente Uniform Cost Search function to solve the game. I implemented BFS and DFS, it worked. But with UCS I have a Segmentation fault which is probably related to my popBest function because BFS and UCS are related. Besides, the segmentation error is also related to temp in my code because there no error when I remove it. Thanks for helping me. Here's my code:
Item* popBest(list_t* list)
{
assert(list);
assert(list->numElements);
assert(list->first);
// the first element is best.
Item* best = list->first;
int minf = best->f;
// Search from the second element (if it exists).
Item* item = best->next;
while (item) {
if (item->f < minf) {
minf = item->f;
best = item;
}
item = item->next;
}
delList(list, best);
return best;
}
void ucs(void)
{
Item *cur_node, *child_p, *temp;
int i;
cur_node->f = 0;
while (listCount(&openList_p)) {
cur_node = popBest(&openList_p);
addFirst(&closedList_p, cur_node);
if (evaluateBoard(cur_node) == 0.0) {
showSolution(cur_node);
printf("\nParcours en largeur (bfs)\n");
return;
}
else {
/* Enumerate adjacent states */
for (i = 0; i < MAX_BOARD; i++) {
child_p = getChildBoard(cur_node, i);
child_p->f = cur_node->f + 1;
if (child_p != NULL) { // it's a valid child!
temp = onList(&openList_p, child_p->board);
/* Ignore this child if already visited */
if (temp == NULL) {
/* Add child node to openList*/
addLast(&openList_p, child_p);
}
else if (temp != NULL && child_p->f < temp->f) {
delList(&openList_p, temp);
addLast(&openList_p, child_p);
}
}
}
}
}
return;
}
Related
I'm currently working on an assignment where the N most frequent words in a book (.txt) must be printed. The issue that I'm currently facing is that when I add a node to one of my trees, it simply replaces the root node and thus, the tree remains as a single node.
Code snippet which adds words from the file "stopwords.txt" to a tree named stopwords:
Dict stopwords = newDict();
if (!readFile("stopwords.txt"))
{
fprintf(stderr, "Can't open stopwords\n");
exit(EXIT_FAILURE);
}
FILE *fp = fopen("stopwords.txt", "r");
while (fgets(buf, MAXLINE, fp) != NULL)
{
token = strtok(buf, "\n");
DictInsert(stopwords, buf); //the root is replaced here
}
fclose(fp);
The data structures are defined as follows:
typedef struct _DictNode *Link;
typedef struct _DictNode
{
WFreq data;
Link left;
Link right;
int height;
} DictNode;
typedef struct _DictRep *Dict;
struct _DictRep
{
Link root;
};
typedef struct _WFreq {
char *word; // word buffer (dynamically allocated)
int freq; // count of number of occurences
} WFreq;
Code to insert and rebalance tree:
// create new empty Dictionary
Dict newDict(void)
{
Dict d = malloc(sizeof(*d));
if (d == NULL)
{
fprintf(stderr, "Insufficient memory!\n");
exit(EXIT_FAILURE);
}
d->root = NULL;
return d;
}
// insert new word into Dictionary
// return pointer to the (word,freq) pair for that word
WFreq *DictInsert(Dict d, char *w)
{
d->root = doInsert(d->root, w); //the root is replaced here before doInsert runs
return DictFind(d, w);
}
static int depth(Link n)
{
if (n == NULL)
return 0;
int ldepth = depth(n->left);
int rdepth = depth(n->right);
return 1 + ((ldepth > rdepth) ? ldepth : rdepth);
}
static Link doInsert(Link n, char *w)
{
if (n == NULL)
{
return newNode(w);
}
// insert recursively
int cmp = strcmp(w, n->data.word);
if (cmp < 0)
{
n->left = doInsert(n->left, w);
}
else if (cmp > 0)
{
n->right = doInsert(n->right, w);
}
else
{ // (cmp == 0)
// if time is already in the tree,
// we can return straight away
return n;
}
// insertion done
// correct the height of the current subtree
n->height = 1 + max(height(n->left), height(n->right));
// rebalance the tree
int dL = depth(n->left);
int dR = depth(n->right);
if ((dL - dR) > 1)
{
dL = depth(n->left->left);
dR = depth(n->left->right);
if ((dL - dR) > 0)
{
n = rotateRight(n);
}
else
{
n->left = rotateLeft(n->left);
n = rotateRight(n);
}
}
else if ((dR - dL) > 1)
{
dL = depth(n->right->left);
dR = depth(n->right->right);
if ((dR - dL) > 0)
{
n = rotateLeft(n);
}
else
{
n->right = rotateRight(n->right);
n = rotateLeft(n);
}
}
return n;
}
static Link newNode(char *w)
{
Link n = malloc(sizeof(*n));
if (n == NULL)
{
fprintf(stderr, "Insufficient memory!\n");
exit(EXIT_FAILURE);
}
n->data.word = w;
n->data.freq = 1;
n->height = 1;
n->left = NULL;
n->right = NULL;
return n;
}
// Rotates the given subtree left and returns the root of the updated
// subtree.
static Link rotateLeft(Link n)
{
if (n == NULL)
return n;
if (n->right == NULL)
return n;
Link rightNode = n->right;
n->right = rightNode->left;
rightNode->left = n;
n->height = max(height(n->left), height(n->right)) + 1;
rightNode->height = max(height(rightNode->right), n->height) + 1;
return rightNode;
}
// Rotates the given subtree right and returns the root of the updated
// subtree.
static Link rotateRight(Link n)
{
if (n == NULL)
return n;
if (n->left == NULL)
return n;
Link leftNode = n->left;
n->left = leftNode->right;
leftNode->right = n;
n->height = max(height(n->left), height(n->right)) + 1;
leftNode->height = max(height(leftNode->right), n->height) + 1;
return leftNode;
}
I believe that most of the code is functional and it is simply the insertion which fails. When I attempted to debug this with gdb, I had discovered that the root node (d->root) was replaced before the recursive insert function (doInsert) was run, causing the program to always return the node n which, as a result, already exists in the tree. For example, if the text file contained the following:
a
b
c
then the program would first insert "a" as stopwords->root, then "b" would replace "a" and become the new stopwords->root, finally "c" would replace "b" as the stopwords->root, resulting in a tree with one node, "c".
There are many inconsistencies in your code.
One mistake is here:
d->root = doInsert(d->root, w);
You reassign unconditionally the root each time when you insert a new node.
You are supposed to return the new node from the function doInsert and to reassign the root only if the new node had become a new root.
But other mistake that you make is that you return from doInsert a local variable n that was not newly allocated but that was initialized to point to the previous root.
Inside doInsert you need to allocate a new node NEW and use a variable x to walk down from the root until you find a place to insert a new allocated node NEW. If x stops at root then you reinitialize the d->root = NEW.
Your function newNode just stores the passed string pointer, so what is pointed at will change when you modify the original string.
To prevent that, you should copy the input string on node insertions.
To archive that,
n->data.word = w;
should be
n->data.word = malloc(strlen(w) + 1);
if (n->data.word == NULL)
{
fprintf(stderr, "Insufficient memory!\n");
exit(EXIT_FAILURE);
}
strcpy(n->data.word, w);
Add #include <string.h> to use strlen() and strcpy() if it isn't.
I'm working on a program that calculates any number in the Fibonacci Sequence without using the int data type since it would overflow. Instead I am using linked lists to hold the digits that represent each number. My current issue is with freeing memory allocated to linked lists that I no longer need. If I'm calculating F(10000), I'd like the thousands of previous lists to be freed. The program as is produces each value up to "F(7) = 13" before crashing and showing "exit status -1". I'd really just like to know what's causing this error and go from there. Any help is appreciated. Thank you and I apologize for the large amount of code.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int digit;
struct Node *next;
} Node;
typedef struct ListyInt
{
Node *head;
int length;
} ListyInt;
Node *create_node(unsigned int digit, ListyInt *listy);
Node *removeNode(Node *node, ListyInt *listy);
void listyPrintHelper(Node *current);
ListyInt *destroyListyInt(ListyInt *listy);
ListyInt *fib(unsigned int n);
void listyPrint(ListyInt *p)
{
if (p == NULL || p->head == NULL)
{
printf("(null pointer)\n");
return;
}
listyPrintHelper(p->head);
printf("\n");
}
void listyPrintHelper(Node *current)
{
if (current == NULL)
return;
listyPrintHelper(current->next);
printf("%d", current->digit);
}
int main()
{
int i;
ListyInt *p;
for (i = 0; i <= 1000; i++)
{
printf("F(%d) = ", i);
listyPrint(p = fib(i));
destroyListyInt(p);
}
return 0;
}
ListyInt *listyAdd(ListyInt *p, ListyInt *q)
{
ListyInt *listy = NULL;
Node *ptemp = NULL;
Node *qtemp = NULL;
Node *temp = NULL;
ListyInt *temp_list = NULL;
unsigned int x = 0;
unsigned int count = 0;
if (p == NULL || q == NULL)
{
return NULL;
}
listy = malloc(sizeof(ListyInt));
if (listy == NULL)
{
return NULL;
}
listy->length = 0;
if (q->length > p->length)
{
temp_list = q;
q = p;
p = temp_list;
}
while (count < p->length)
{
if (count == 0)
{
x = p->head->digit + q->head->digit;
ptemp = p->head->next;
qtemp = q->head->next;
listy->head = create_node(x, listy);
temp = listy->head;
temp->next = create_node(0, listy);
if (temp->digit > 9)
{
temp->digit = temp->digit - 10;
temp->next->digit = temp->next->digit + 1;
}
}
else
{
temp->next->next = create_node(0, listy);
if (qtemp == NULL)
{
temp->next->digit += ptemp->digit;
ptemp = ptemp->next;
temp = temp->next;
}
else
{
x = ptemp->digit + qtemp->digit;
temp->next->digit += x;
if (temp->next->digit > 9)
{
temp->next->digit = temp->next->digit - 10;
temp->next->next->digit = temp->next->next->digit + 1;
}
qtemp = qtemp->next;
ptemp = ptemp->next;
temp = temp->next;
}
}
if (count == p->length - 1 && temp->next->digit == 0)
{
temp->next = removeNode(temp->next, listy);
}
count++;
}
return listy;
}
ListyInt *destroyListyInt(ListyInt *listy)
{
if (listy == NULL)
{
return NULL;
}
Node *current = listy->head;
Node *temp;
while (current != NULL)
{
temp = current->next;
free(current);
current = temp;
}
free(listy);
return NULL;
}
ListyInt *fib(unsigned int n)
{
ListyInt *spiral = malloc(sizeof(ListyInt));
ListyInt *p = NULL;
ListyInt *q = NULL;
unsigned int count = 2;
if (spiral == NULL)
{
return NULL;
}
if (n == 0)
{
spiral->head = create_node(0, spiral);
return spiral;
}
if (n == 1)
{
spiral->head = create_node(1, spiral);
return spiral;
}
p = malloc(sizeof(ListyInt));
p->head = create_node(0, p);
q = malloc(sizeof(ListyInt));
q->head = create_node(1, q);
while (count <= n)
{
spiral = listyAdd(p, q);
destroyListyInt(p);
p = q;
q = spiral;
count++;
}
return spiral;
}
Node *create_node(unsigned int digit, ListyInt *listy)
{
if (listy == NULL)
{
return NULL;
}
Node *new_node = malloc(sizeof(Node));
new_node->digit = digit;
new_node->next = NULL;
listy->length++;
return new_node;
}
Node *removeNode(Node *node, ListyInt *listy)
{
if (node == NULL)
{
return NULL;
}
if (listy == NULL)
{
return NULL;
}
free(node);
node = NULL;
listy->length--;
return NULL;
}
I'd really just like to know what's causing this error and go from there.
Long story short, C's equivalent of a NullPointerException, as far as I can tell.
Long story longer, I haven't had time to fully examine your code or debug it, but I have had time to run it through gdb, which is included with most Linux installations. If you're using Visual Studio, I vaguely remember there being a debug mode, which should show you roughly the same information, just in a different place. This is GDB's output:
Starting program: /home/ubuntu/C/a.out
F(0) = 0
F(1) = 1
F(2) = 1
F(3) = 2
F(4) = 3
F(5) = 5
F(6) = 8
F(7) = 13
Program received signal SIGSEGV, Segmentation fault.
0x00000000004008db in listyAdd (p=0x6036a0, q=0x6036e0) at main.c:117
117 temp->next->digit += ptemp->digit;
(Okay, that's not all of it, but that's the relevant bit.)
What those last three lines mean is that you got a segfault. There are a bunch of things that can cause it, but based on that line, it looks like it's been caused by trying to dereference an invalid pointer. That's either a NULL pointer (a value of 0x0) or a pointer you've already freed.
If you're on Linux, you can then run Valgrind on it to figure out what, exactly, happened. It'll tell you if it's using a freed pointer or a NULL one, and that'll give you a good starting point to find the actual bug. You can also use your IDE's debugger (or GDB, if you want to try playing with the command-line version, but I wouldn't recommend it) to step through your program and see what the values of the variables involved are, which you can walk backwards from to see where they're being changed and invalidated.
If I had to guess, though, I'd say 0andriy's comments hit it on the nose -- you seem to be freeing things twice, and you probably meant to free them once, at the end.
I'm somewhat intentionally leaving this vague. Segfaults are common and (as you've noticed) difficult to debug, and you can only really learn how through experience. I think being shown the answer would honestly be less helpful than working through it yourself, and with tools like Valgrind and your debugger, that's not actually that hard, just tedious.
I found the issue. It was because the length of my linked lists weren't being reset when fib() was called. Thanks for your help everyone.
I have an AVL Tree implementation that can successfully build a tree by insertions. Rotations etc. also work fine. However my delete function has problems. It poorly balances and sometimes crashes. To me, the rotations make sense (I've commented appropriate places) but somehow it doesn't work. How can I fix this?
void delete_elem(node** t, int val, uint delete_flag) {
if(!(*t))
return;
if((*t)->data < val)
delete_elem(&(*t)->right, val, delete_flag);
else if((*t)->data > val)
delete_elem(&(*t)->left, val, delete_flag);
else { // found elem
// if there's a duplicate, remove it
if(delete_flag == DELETE_NO_FORCE && (*t)->dup_count) {
--(*t)->dup_count;
printf("Duplicate element removed. %d left.\n", (*t)->dup_count);
}
else { // there were no duplicates
node* del;
if(!(*t)->left && (*t)->right) { // no left but right
del = (*t);
(*t) = (*t)->right;
free(del);
}
else if(!(*t)->right && (*t)->left) { // no right but left
del = (*t);
(*t) = (*t)->left;
free(del);
}
else if(!(*t)->left && !(*t)->right) { // additionally, you can use the is_leaf function we wrote before, in here
free(*t);
*t = NULL;
}
else { // has both children
del = get_successor(*t, *t); // get the in-order successor in tree *t of *t
printf("succ of %d is %d.\n", (*t)->data, del->data);
(*t)->data = del->data; // swap the successor's data with t's data
(*t)->dup_count = del->dup_count; // IMPORTANT! We support duplicates! Duplicate count must also be swapped!
delete_elem(&(*t)->right, del->data, DELETE_FORCE); // We must now delete this guy forcefully!
}
if(!(*t)) // if t was deleted and not needed anymore, don't bother. Update height if it exists
return;
(*t)->height = Max(get_height((*t)->left), get_height((*t)->right)) + 1;
int bfactor = get_balance(*t);
if(bfactor > 1 && get_balance((*t)->left) > 0)
rotate_once_right(t);
else if(bfactor > 1 && get_balance((*t)->left) < 0)
rotate_twice_left(t);
else if(bfactor < -1 && get_balance((*t)->right) > 0)
rotate_once_left(t);
else if(bfactor < -1 && get_balance((*t)->right) < 0)
rotate_twice_right(t);
}
}
}
The above is my delete function.
The following are some screenshots of the crash occuring:
These are my rotation functions. They seem to be working right, as everytime I create a tree, it's always reported to be an AVL Tree. However, just in case:
void rotate_once_left(node** k1) {
node* temp = (*k1)->left;
(*k1)->left = temp->right;
temp->right = *k1;
(*k1)->height = Max(get_height((*k1)->left), get_height((*k1)->right)) + 1;
temp->height = Max(get_height(temp->left), (*k1)->height) + 1;
*k1 = temp;
}
void rotate_once_right(node** k1) {
node* temp = (*k1)->right;
(*k1)->right = temp->left;
temp->left = *k1;
(*k1)->height = Max(get_height((*k1)->left), get_height((*k1)->right)) + 1;
temp->height = Max(get_height(temp->right), (*k1)->height) + 1;
*k1 = temp;
}
void rotate_twice_left(node** k1) {
rotate_once_right(&(*k1)->left);
rotate_once_left(k1);
}
void rotate_twice_right(node** k1) {
rotate_once_left(&(*k1)->right);
rotate_once_right(k1);
}
Update: No more crash, but some unbalance is left after deletion. Sample test case:
I am trying to make a students list for a project in c
the functions inside the program are 3
insert = inserts students to the list
print = prints out the students available
delete = deletes a student from the list
I have created the program and it works fine using all three functions
and now I would like to make the same list using recursion.
I have made the print function recursive and it is working
now I am trying to make the delete function work the same way
unfortunately I am failing to make it work
In the code below if you run it you will see that it works only if you do not attempt to delete the last node on the list and if you do not tell it to delete a node that it does not exists.
#include <stdio.h>
#include <stdlib.h>
typedef struct tf *tp;
struct tf{
int am;
double gr;
tp next;
};
tp head, tail, temp, aux;
void insert1 (tp *h, tp t);
void print1(tp h);
void delete1(tp *h,int da);
int main()
{
char fry, fry2;
int am;
fry = 'a';
head = NULL;
tail = NULL;
while (fry != 'q')
{
printf("\n character given is %c\n", fry);
if (fry != 'q')
{
printf("new choice\n");
fry = 'a';
fflush(stdin);
fry = getchar();
getchar();
if (fry == 'q')
printf("quit\n");
if (fry == 'i')
{
fry2 = fry;
printf(" insert new student number am\n");
insert1(&head,tail);
fry = fry2;
}
if (fry == 'd')
{printf(" delete \n");
printf(" am number of student to be deleted\n");
scanf("%d", &am);
delete1(&head,am);
}
if (fry == 'p')
{
printf("\n printing\n");
print1(head);
}
}
}
}
void insert1 (tp *h, tp t)
{
tp te, a;
int da;
te = (tp)malloc(sizeof(struct tf));
printf(" am number for the new insert\n");
scanf("%d", &da);
getchar();
te->am = da;
te->next = NULL;
printf("am number is %d",te->am);
if ((*h != NULL) && (te->am < (*h)->am))
{
te->next = *h;
*h = te;
}
if((*h != NULL) && ((*h)->next != NULL) && (te->am > (*h)->am))
{
a=*h;
while((a->next != NULL) && (a->next->am < te->am))
{
a= a->next;
}
te->next = a->next;
a->next = te;
}
if((*h != NULL) && ((*h)->next == NULL) && (te->am > (*h)->am))
{
(*h)->next = te;
}
if(*h == NULL)
{
printf("\n head is null");
*h = te;
t = te;
}
}
void print1(tp h)
{
tp a;
a=h;
if (a==NULL)
return;
printf("%d\n",a->am);
print1(a->next);
}
void delete1(tp *h,int da)
{
tp a= *h,t= *h,temp = NULL;
if ((*h) != NULL)
{
if ((*h)->am!=da)
{
if (a->next->am != da && a->next!=NULL)
{
delete1(a->next,da);
}
else
{
if (a->next==NULL)
{
printf("am not found\n");
return;
}
else
{
temp = a->next;
a->next = a->next->next;
free(temp);
}
}
}
else
{
a = (*h);
(*h)= (*h)->next;
free(a);
}
}
else
{
printf("empty list");
}
}
As you can see I want the delete function to delete the node by looking for the am number given,so it will first search the list to find if the am number is there or not.
If anyone can give me a tip on how to make the delete function to work I would be grateful.
There are several things going on. This line:
if (a->next->am != da && a->next!=NULL) ...
should have the conditions swapped, otherwise you might access a->next withot verifying that it isn't NULL first. The auxiliary variable a and the other temporaries are confusing rather than helpful.
You pass the head to the delete1 function as pointer to pointer, so that the head can be updated. But this doesn't affect only the head: This adds a level of indirection thoughout your iteration.
For your iterative calls, this means that you must pass the address of the pointer that stores the reference to the current node, (*h)->next. At the beginning, this is the address of the head. On subsequent iterations, this is the address of the next pointer of the previous node.
There's also no need to consider various cases. The code can be as simple as:
void delete1(tp *h, int da)
{
if (*h != NULL) {
if ((*h)->am == da) {
tp next = (*h)->next;
free(*h);
*h = next;
return;
}
delete1(&(*h)->next, da);
}
}
The recursive call happens at the end of the function or it doesn't happen at all. This means that you can rewrite the code as a loop:
void delete1(tp *h, int da)
{
while (*h != NULL) {
if ((*h)->am == da) {
tp next = (*h)->next;
free(*h);
*h = next;
return;
}
h = &(*h)->next;
}
}
This will save you some stack space on large lists. Your insert1 function could also be cleaned up and simplified.
If someone could help me find where i am going wrong, i have been working on this code for a long time but cannot get it right.
It takes a linked list to be sorted by passing *head as head pointer. The output of that function should be the same linked list sorted in ascending order such that the header node will be the smallest value in the
list.
void sortByCount (struct lnode** head) {
struct lnode* temp= (*head);
struct lnode* temp2 = (*head);
int i;
int j;
int counter = 0;
while(temp != NULL)
{
temp = nodeGetNext(temp);
counter++;
}
for( i = 1; i<counter; i++)
{
temp2=(*head);
bool flag = false;
for(j = 1; j<counter-i+1;j++)
{
if(countCmp(temp2,nodeGetNext(temp2))>0)
{
swap(head,temp2,nodeGetNext(temp2));
}
if(countCmp(temp2,nodeGetNext(temp2))== 0 && (wordCmp(temp2,nodeGetNext(temp2))>0))
{
swap(head,temp2,nodeGetNext(temp2));
flag = true;
//continue;
}
}
temp2 = nodeGetNext(temp2);
}
}
The problem is in this part of your loop:
if(countCmp(temp2,nodeGetNext(temp2))>0)
{
swap(head,temp2,nodeGetNext(temp2));
}
if(countCmp(temp2,nodeGetNext(temp2))== 0
&& (wordCmp(temp2,nodeGetNext(temp2))>0))
{
swap(head,temp2,nodeGetNext(temp2));
flag = true;
//continue;
}
If you decide to bubble up, and swap, then the second if check might choose to bubble up again (since the swap has happened, the next of temp2 will have changed). This is probably not what you intended. Instead, you probably meant to do the second if check only if the first if check failed. This is normally accomplished by adding an else to the if statement.