I'm trying to delete all nodes from my queue of structures.
Structure:
struct element{
int id;
int sign;
int year;
int month;
double amount;
struct element *next;
};
struct queue{
struct element *head;
int size;
};
And the function I wrote:
void delete(struct queue *queue) {
if (queue->size == 0){
printf("Structure is empty\n");
}
else {
struct element* this;
struct element* other;
for(this=queue->head;this!=NULL;this=other)
{
other=this->next;
free(this);
}
free(queue);
}
}
It doesn't work, and I'm out of ideas. Any suggestions?
In your delete routine, you do not free the queue if the size is empty, but you do free it if the size is non-empty. You should probably do the same for both cases. That is, either don't free in both places, or free in both places.
It is bothersome to need to figure out what the right thing to do is, because delete can not know how the queue was allocated. Given your current design, a way out may be to pass a flag to delete to indicate what it should do:
void delete(struct queue *queue, int do_free) {
if (queue->size == 0){
printf("Structure is empty\n");
}
else {
struct element* this;
struct element* other;
for(this=queue->head;this!=NULL;this=other) {
other=this->next;
free(this);
}
queue->head = 0;
queue->size = 0;
}
if (do_free) free(queue);
}
struct queue new;
/* ... */
delete(&new, 0); /* don't free the queue */
struct queue *empty_new = malloc(sizeof(struct queue));
empty_new->size = 0;
delete(empty_new, 1); /* free the empty queue */
Here
struct queue new;
//...
delete(&new);
new is allocated on the stack, so don't call free(queue) in delete.
Instead, set queue->head = NULL; queue->size = 0; to indicate that the queue is now empty as mentioned by #kirill.
How about just passing the first element of the queue.
void delete(element *el ) {
if(el) {
delete(el->next );
free(el);
}
}
with
typedef struct _element{
int id;
int sign;
int year;
int month;
double amount;
struct _element *next;
} element;
you might have forgotten to update at the end of the function the pointer to NULL as well as changing the size of the queue to 0.
Related
In my structure struct ListNode I am making a int type variable key but it is necessary to make that in the struct Listnode can we make that inside HashTableNode because when two or more items will be there in HashTableNode (that is when collision will be more in single table node) than we have to create more linked list node and every time inside that node key variable will consume some memory if we can define that inside HashTableNode than we can save memory.
Is it correct to mention the key in each list node so that we can access at any time whenever we need because the below hash table implementation is from very famous book of data structures.
Please tell me what i mentioned above is correct
Because i am a beginner if Not then please correct me
#define Load_factor 20
#include<stdio.h>
#include<stdlib.h>
struct Listnode{
int key;
int data;
struct Listnode* next;
};
struct HashTableNode{
int bcount; /// Number of elements in block
struct Listnode* next;
};
struct HashTable{
int tsize; /// Table size
int count;
struct HashTableNode** Table;
};
struct HashTable* createHashTable(int size){
struct HashTable* h;
h=(struct HashTable*)malloc(sizeof(struct HashTable));
h->tsize=size/Load_factor;
h->count=0;
h->Table=(struct HashTableNode**)malloc(sizeof(struct HashTableNode*)*h->tsize);
if(!h->Table){
printf("Memory Error");
return NULL;
}
for(int i=0;i<h->tsize;i++){
h->Table[i]->bcount=0;
h->Table[i]->next=NULL;
}
return h;
}
int HASH(int data,int tsize){
return(data%tsize);
}
/// Hashsearch
int HashSearch(struct HashTable* h,int data){
struct Listnode* temp;
temp=h->Table[HASH(data,h->tsize)]->next;
while(temp) ///same as temp!=NULL
{
if(temp->data==data)
return 1;
temp=temp->next;
}
return 0;
}
int HashDelete(struct HashTable* h,int data)
{
int index;
struct Listnode *temp,*prev;
index=HASH(data,h->tsize);
for(temp=h->Table[index]->next,prev=NULL;temp;prev=temp,temp=temp->next)
{
if(temp->data==data)
{
if(prev!=NULL)
prev->next=temp->next;
free(temp);
h->Table[index]->bcount--;
h->count--;
return 1;
}
}
return 0;
}
int HashInsert(struct HashTable *h ,int data){
int index;
struct Listnode* temp,*newnode;
if(HashSearch(h,data))
return 0;
index = HASH(data,h->tsize);
temp=h->Table[index]->next;
newnode=(struct Listnode*)malloc(sizeof(struct Listnode));
if(!newnode)
return -1;
newnode->key=index;
newnode->data;
newnode->next=h->Table[index]->next;
h->Table[index]->next=newnode;
h->Table[index]->bcount++;
h->count++;
return 1;
}
It is necessary to store key for every node because it is used to resolve collisions. Please note that the collision happens to the hash value and not the key, which means that every element (Listnode) in the same bucket (HashTableNode) will still have a different key so you can't optimize it away.
However, in your example the data is the key (which is usually called a HashSet as opposed to HashMap), so there is really no need for the key field in the Listnode.
I'm using malloc() function in order to create a queue in C, the problem is that when I use the dequeue() function I leave an unreferenced element. I have to use this function lots of times per second, so I would like to know which is the best way to handle it or if there is a better way than using malloc(). These are the two functions:
void enqueue(struct Queue *q, char c){
//adds an element to the queue
struct Member* m = malloc(sizeof *m);//in order to make m global
if(!m){ perror("malloc");exit(EXIT_FAILURE);}
if(q->length == 0){
m->ch = c;
q->first = m;
q->last = m;
}else{
m->ch = c;
q->last->next = m;
q->last = m;
}
q->length++;
}
char dequeue(struct Queue *q){
//returns the first element of the queue an delete it
char c;
if(q->length >0){
q->length--;
c = q->first->ch;
q->first= q->first->next;
//CLEAR THE UNREFERENCED VARIABLE
}
return c;
}
Thanks!
EDIT:
These are the structs that I'm using:
typedef struct Queue{
int length;
struct Member *first;
struct Member *last;
}Queue;
typedef struct Member{
char ch;
struct Member *next;
}Member;
Store the unreferenced variable to a temporary variable first so that you can free it after changing the first node of the queue.
//returns the first element of the queue and delete it
char dequeue(struct Queue *q){
struct Member* temp = q->first;;
char c;
if(q->length >0){
q->length--;
c = q->first->ch;
q->first= q->first->next;
free(temp);
}
return c;
}
You can check more about free here.
I have the following code in C, trying to develop an Operating System simulation:
Queue.c:
typedef enum {running,readyproc,waiting,suspended}status;
typedef struct pcb {
long pid;
char* pname;
long priority;
long sleepperiod;
long* context;
status stat;
}PCB;
typedef enum {ready, timer, suspend} queuetype;
typedef struct {
int size;
int capacity;
PCB ** data;
queuetype qt;
}Queue;
void queue_init(Queue *q, queuetype qt){
q->size =0;
q->capacity = QUEUE_INITIAL_CAPACITY ;//100
q->data = (PCB **)calloc(q->capacity,sizeof(PCB*));
q->qt = qt;
}
PCB* queue_pop (Queue* q){
PCB* toReturn;
int i;
toReturn = q->data[0];
for (i=0;i<q->size;i++){
q->data[i]=q->data [i+1];
}
free(q->data[q->size]);
q->size--;
printf ("toReturn id:%ld pname: %s\n", toReturn->pid, toReturn->pname);
return toReturn;
}
Knowing that the queue gets initialized and filled with PCBs. I do always get a segafault on calling:
PCB* pcb = queue_pop(&queue);
EDIT:
Here is the function that would fill the queue:
void queue_append(Queue *q, PCB* value)
{
q->data[q->size++] = value;
}
EDIT2:
the printf before the return in queue_pop returns this:
toReturn id: 2 pname: test1c_a
which corresponds to what I want to pop from that queue.
for (i=0;i<q->size;i++){
q->data[i]=q->data [i+1];
}
If q->size == q->capacity, then you'll run off the end of q->data (it will access q->data[q->capacity], which is one past its allocation length).
P.S. There are much more efficient ways to do this.
Below seems to be a problem.
free(q->data[q->size]);
lets say two elements are in Queue q->size = 2 hold by
q->data[0] and q->data[1]
so when queue_pop called. Above code will free q->data[2]. This may leads to seg-fault.
I could use a little help. I'm trying to sort a queue of structures by year.
This are my structures:
struct element{
int id;
int sign;
int year;
int month;
double amount;
struct element *next;
};
struct queue{
struct element *head;
struct element *tail;
struct element *heads;
struct element *temp;
struct element *temph;
int size;
};
and this is the function i wrote:
void sort(struct queue* queue){
if (queue->size == 0){
printf("Struct is empty\n");}
else {
struct element* head=queue->head;
struct element* heads=queue->heads;
struct element* temp=NULL;
struct element* temph=queue->head;
int i, size=queue->size;
for(i=0;i<size-1;i++){
heads=head->next;
if((head->year)>(heads->year)){
temp=head;
head=heads;
heads=temp;
}
head=head->next;
heads=NULL;
temp=NULL;
}
head=temph;
}
}
It breaks when I copmare: if((head->year)>(heads->year)).
I'm pretty sure that my problem is caused by improper reference to the structure next to head (I named it heads).
I omitted all the non-important stuff, and reduced the linked-list bubbele sort to this skeletton.
void sort(struct queue* queue)
{
struct element **pp, *this;
if (!queue->head ){
fprintf(stderr, "OMG Struct is empty\n");
return;
}
for(pp = &queue->head; this = *pp; pp = &(*pp)->next){
struct element *other = this->next;
if (!this->next) break;
if (this->year < other->year) continue;
/*
** Now, Swap this (b) and other (c)
** old situation: #a -> (b) -> (c) -> (d)
** new situation: #a -> (c) -> (b) -> (d)
*/
*pp = other; /* #a -> (c) */
this->next = other->next; /* (b) -> (d) */
other->next = this; /* (c) -> (b) */
}
/* Note: when we get here, "this" will contain the last non-NULL node in the
** chain, and can be used to reset the tail-pointer
*/
return;
}
i have a dynamic number of pointers all having the same size. i need to store all the addresses of my pointers in some place like a link List in order to fetch them later on.
my question is what structs should i use. is the following correct:
struct Node{
int *k;
Node*Next;
}
struct LS{
Node*first,*last;
void push(Node*n);
Node* GetFirst();
Node* GetLast();
}
the LS is the linked list that stores Nodes. and a Node is a struct that holds the address of my pointer and a pointer to the next Node.
am i using int *k to store the address of my pointer correctly? should i continue with this implementation or is there any easier way to do this?
this sample code may help you start...
#include <stdio.h>
struct Node{
int *k;
Node *Next;
}* Temp;
struct LS
{
Node *first,*last;
void push(Node *MyNode)
{
MyNode->Next=NULL;
if(empty())
{
first=MyNode;
last=MyNode;
}
else
{
last->Next = MyNode;
last=MyNode;
}
}
Node* front()
{
return first;
}
void pop()
{
free(first->k);
first=first->Next;
}
bool empty()
{
if(first==NULL) return true;
return false;
}
};
int N=10;
int main()
{
LS Q;Q.first=NULL;
for(int i=0;i<3;i++)
{
Node *NewNode= (Node*)malloc(sizeof(Node));
NewNode->k = (int*)malloc(sizeof(int)*N);
for(int k=0;k<N;k++) NewNode->k[k]=i;
Q.push(NewNode);
}
while(!Q.empty())
{
Temp=Q.front();
for(int i=0;i<N;i++) printf("%d ",Temp->k[i]);
printf("\n");
Q.pop();
}
return 1;
}
Yes, your Node struct is correct.
As to whether there is an easier way it depends. If there is a maximum number of pointers that you will need then an array of pointers would be easier. If you can do it in C++ then an STL vector (can use it like an array, but underneath the hood it can grow dynamically as needed) is easier. If you have to do it in C and it has to be dynamic, though, then no, there is not an easier way.
WDM.H (microsoft header) has a bunch of linked list stuff to look at ( http://msdn.microsoft.com/en-us/library/ff547799(VS.85).aspx ) , I've cut and pasted from that, and added a very simple example.
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;
typedef struct _MY_THING
{
LIST_ENTRY ListEntry;
ULONG randomdata1;
ULONG randomdata2;
ULONG randomdata3;
ULONG randomdata4;
} MY_THING, *PMY_THING;
#define CONTAINING_RECORD(address, type, field) ((type *)( \
(PCHAR)(address) - \
(ULONG_PTR)(&((type *)0)->field)))
VOID
InsertHeadList(
IN PLIST_ENTRY ListHead,
IN PLIST_ENTRY Entry
)
{
PLIST_ENTRY Flink;
Flink = ListHead->Flink;
Entry->Flink = Flink;
Entry->Blink = ListHead;
Flink->Blink = Entry;
ListHead->Flink = Entry;
}
VOID
InitializeListHead(
IN PLIST_ENTRY ListHead
)
{
ListHead->Flink = ListHead->Blink = ListHead;
}
PLIST_ENTRY
RemoveHeadList(
IN PLIST_ENTRY ListHead
)
{
PLIST_ENTRY Flink;
PLIST_ENTRY Entry;
Entry = ListHead->Flink;
Flink = Entry->Flink;
ListHead->Flink = Flink;
Flink->Blink = ListHead;
return Entry;
}
void main()
{
LIST_ENTRY HeadOfMyList;
MY_THING Thing;
InitializeListHead(&Head);
// example of add thing to list.
InsertHeadList(&HeadOfMyList, &Thing.ListEntry);
// example of removing thing from the list
PLIST_ENTRY listEntry = RemoveHeadList(&HeadOfMyList);
PMY_THING pThing = (PMY_THING) CONTAINING_RECORD(listEntry, MY_THING, ListEntry);
}