implement of a queue(fifo) - c

Iv'e been given a mission to implement a dynamic queue in c language without any loops and any recursion.
the queue should contain the next function: installation, destruct, add, remove and peek.
I thought to make a link structure, that way each link will have a pointer the next link and so on..but the problem is that I don't know how to do the destruct function without any loops, the only solution I can think of is making a loop that will send each one of the links to the remove function(but again, I need to it without any loops). Is their any possibility to do the destruct function without any loops?
p.s the destruct function should free all of the memory that we used for the queue.

If a recursing function doesn't count as a loop for your constrains, you could use recursion to traverse the list and destroy the items.
Another approach is to store items in an array, and maintain a pointer into the array for the head and tail of the queue. Destroying the queue just means freeing the array or resetting the head/tail pointers, and no loops would be required.

There's no real need to make a queue based on a linked list, it would have all the downside of random allocated elements and lack of spatial locality, would be relatively harder to debug, and won't use the main benefit of a linked list (insertion at O(1)) since it's a queue with only one insertion point anyway (or 2 for a double-ended one).
Instead you could use an array, and maintain a head and tail index variables, use cyclic incrementation when they wrap around at the end, and reallocate when required. If the queue holds basic data types this would also allow you to deallocate the entire queue in one go, just free the array (although for elements you had to manually allocate, I can't see any way to avoid iterated removal, unless you move to c++).

I am assuming that the item to be inserted in memory is of constant size. If needed, it could be a pointer to a block of memory. In that case, you can use a circular buffer with a head and tail pointer. When either pointer "gets to the end of the block" it should wrap - i.e. you increment / decrement modulo queue size.
Initialization:
Create a memory space of finite size (max size of the buffer)
Add:
Update memory location at the current tail (if add to end)
or head (if add to beginning), and update the tail/head pointer.
Remove:
Read the data at the head/tail, and update the pointer
Peek:
Read the data at the head/tail, and don't move the pointer
Destruct:
Free the memory block
No loops, no recursion. It uses the fact that a FIFO buffer only allows changes at the beginning / end of the queue- it is not possible to remove elements "in the middle".
If the head and tail pointers meet, the queue is "full". In that case, the "insert" function should return an error, unless you add a "insert destructively" flag that says "overwrite the oldest element". That seems beyond the scope of your homework, but it is important in real life applications. Sometimes you care about the oldest data - at other times you care about the latest data. But usually, if your queue is filling up, there is a problem with the over all system design (you didn't scale the process that empties the queue to deal with the rate at which it is filling, basically).
Note - if each element in the queue is a pointer to dynamically allocated memory you WILL need to iterate over all elements to free that memory, or you will create a memory leak. But if the queue is of constant size, this is not needed. Given the constraints given, and the lack of specification that queue element size should be variable, I would recommend you write your solution for a fixed size queue element.

Related

Sentinel vs. passing around a count

I have a structure in C which contains an array on which I perform stack operations.
If the stack is full, I need to prevent pushing an element past the end of the array, and return an error condition.
Is it better style to include the size of the stack as an element of the structure, and pass that number of elements to the stack_push() function, or should I have a sentinel element at the end of the stack array?
How are you going to implement your stack_push() function?
If it requires scanning to the end of the array looking for an empty slot to insert the pushed element into, then you need a sentinel value anyway (e.g., NULL, if the array contains pointer elements). But note that the algorithm is going to be O(N).
On the other hand, keeping track of the number of active elements within the array allows your algorithm to be O(1) for pushes (and also for pops). It also saves you the trouble of allocating one extra element in the array, which may be significant if it's an array of structs.
Generally speaking, most stack data structures are implemented using an array and a counter.
What sentinel value would you use? Of course, you have to be sure that the caller of this function will definitely never use this value. It could be very confusing to debug if your function is stopping prematurely at a sentinel value that seems like a reasonable input.
For things like strings, it is easy to use a NULL to terminate because a string should never have a zero byte. However, if you start using sentinels in some places and not in others, it can start to get very confusing for developers that are trying to use your code.
I would say to use a size argument unless there is a VERY clear and obvious choice of sentinel, and probably not even then.

How do I add/subtract pointers to different sections of the heap (in C)

In a program I'm writing, I am implementing binary tree and linked list structures; because I don't know how many nodes I will need, I am putting them on the heap and having the program use realloc() if they need more room.
The problem is that such structures include pointers to other locations in the same structure, and because the realloc() moves the structure, I need to redo all those pointers (unless I change them to offsets, but that increases the complexity of the code and the cost of using the structure, which is far more common than the reallocations).
Now, this might not be a problem; I could just take the old pointer, subtract it from the new pointer, and add the result to each of the pointers I need to change. However, this only works if it is possible to subtract two pointers and get the difference in their addresses (and then add that difference to another pointer to get the pointer that many bytes ahead); because I'm working on the heap, I can't guarantee that the difference of addresses will be divisible by the size of the entries, so normal pointer subtraction (which gives the number of objects in between) will introduce errors. So how do I make it give me the difference in bytes, and work even when they are in two different sections of the heap?
To get the difference between two pointers in bytes, cast them to char *:
(char *) ptrA - (char *) ptrB;
However, if you'd like to implement a binary tree or linked list with all nodes sharing the same block of memory, consider using an array of structs instead, with the pointers being replaced by array indices. The primary advantage of using pointers for a linked list or tree, rather than an array of structs, is that you can add or remove nodes individually without reallocating memory or moving other nodes around, but by making the nodes share the same array, you're negating this advantage.
The best way would indeed be to malloc() a new chunk for every node you have. But this might have some overhead for the internal management of the memory, so if you have lots of them, it might be useful to indeed allocate space fore more nodes at once.
If you need to realloc then, you should go another way:
1. Calculate the offset within your memory block: `ofs = ptrX - start`
2. Add this offset to the new address returned by `realloc()`.
This way, you always stay inside the area you allocated and don't have strange heap pointer differences with nearly no meaning.
In fact ,you can use malloc or calloc to get memory for each node.
So you only need to remeber the address of tree's root node.
In this way, you never need realloc memeory for the whole tree . The address of each node also never change . :)

Separating the linked list implementation from the malloc function

I have been told to design a linked list module where the linked list functions will all be in one header file but the memory allocation(malloc) will not happen those modules.
The memory allocation should ONLY happen in the main function. I am unable to figure it out. Do help me.
that has been implemented already: look at <sys/queue.h> that's a header only linked list.
In main you should allocate a sufficiently large amount of memory (A memory pool), in one go. Now in your module you need to manage (allocate and free) memory chunks from this pool, and not bother with malloc.
If you don't know about memory pool, read this - http://en.wikipedia.org/wiki/Memory_pool.
However there is problem of fragmentation, which you need to tackle. In the steps below I use a bit array, to mark the free and allocated nodes.
Example-
In main you allocate 50*sizeof(node) (50 depends on application)
Now, you pass the pointer of allocated pool to your function.
Keep a counter, to count number of allocated nodes, initialize it to 0
Also keep a bit array, of size 50, initialized to 0 (all free)
When allocating, check for overflow, iterate over the bit-array, to find first free node. If j th bit is 0, pass on the address of new node as Base + j(*sizeof node), and increment the counter. Set the j th bit to 1.
When deallocating, simply decrement the counter, and set the corresponding bit to 0.
HTH
You can do this as an array of structures and link it by array index. That array can then be allocated in the main function. Note that you have to keep track of the number of entries you have in your list, as the list will be limited to the number of entries you allocate.

Opinions and suggestions regarding my approach to first fit malloc function

I'm writing a malloc function for a college assignment. Here's a basic layout of my idea:
1)Define a node struct with pointers to previous node, next node, as well as a char for size and vacancy. Each region in the heap will contain a hidden node with this information.
2)Malloc function. Starting with first node loop through each node checking for vacancy. If a node is vacant and is large enough return a ptr to the beginning of the region not including the node. If no space is available use sbrk to allocate requested space PLUS space for a node.
3)Free function. Go to pointer passed as parameter-sizeof(struct node) and set the vacancy to vacant. Then starting with the beginning of the list, traverse the list merging adjacent free spaces.
How does this approach sound? My main concern is with actually starting the linked list. For instance, should I create a node with sbrk before I start to do any allocations and store a ptr to it as a global variable? If so how do I initialize a first node before I allow the malloc function to be called by a driver program?
Thanks in advance. I'm not asking for someone to write my code, only to provide some insight and suggestions regarding my ideas.
I would avoid keeping all the bookkeeping information on nodes while they're allocated. I'd have the bare minimum of information (usually just the block size) at the beginning of the block, but nothing more.
I'd track free blocks and allocated blocks separately, so when you're searching for a free block, you don't waste time on blocks that are already in use.
I'd separate the free list into two pieces, and coalesce blocks lazily. In other words, have one free list you're allocating from, and a second that's just a holding area. When the user calls free, just link the block into the holding area, nothing more. When the list you're using for allocations starts to run low, sort the blocks in the holding area by address, then merge with the allocation free list. Then walk the list and merge adjacent blocks.
When you do need to call sbrk (or whatever) to allocate more space from the system, do not just allocate enough space to satisfy the current allocation request. Instead, allocate a fairly large block (e.g., a megabyte) and then split that to get satisfy the request, and add the rest as block to the free list. If you're running low enough on memory that you have to go to sbrk once, chances are the next few calls will do the same, so you might as well be greedy, and grab enough memory immediately to stand a decent chance of satisfying more requests as well.
The basic idea of the third is to avoid doing coalescing as long as possible to increase the chances of finding adjacent blocks, so when you do coalesce you'll probably do some real good, and avoid wasting time trying to coalesce when there are only a few adjacent blocks free.

difference between array and list

what is the difference between array and list?
In C, an array is a fixed-size region of contiguous storage containing multiple objects, one after the other. This array is an "object" in the meaning which C gives to the word - basically just some memory that represents something. An object could just be an int.
You can distinguish slightly between array objects, and array types. Often people use array objects which are allocated with malloc, and used via a pointer to the first element. But C does also have specific types for arrays of different sizes, and also for variable-length-arrays, whose size is set when they are created. VLAs have a slightly misleading name: the size is only "variable" in the sense that it isn't fixed at compile time. It can't change during the lifetime of the object.
So, when I say an array is fixed-size I mean that the size cannot change once the array is created, and this includes VLAs. There is realloc, which logically returns a pointer to a new array that replaces the old one, but can sometimes return the same address passed in, having changed the size of the array in place. realloc operates on memory allocations, not on arrays in general.
That's what an array is. The C programming language doesn't define anything called a list. Can't really compare something which is well defined, with something that isn't defined ;-) Usually "list" would mean a linked list, but in some contexts or in other languages it means other things.
For that matter, in other languages "array" could mean other things, although I can't immediately think of a language where it means anything very different from a C array.
If your question really has nothing to do with C, and is a language-agnostic data-structures question, "what is the difference between an array and a linked list?", then it's a duplicate of this:
Array versus linked-list
There is no such thing as a standard list in C. There is such a thing in C++, where it is implemented as a double-linked list.
The main differences are that arrays have random access - you can access any member of the array in O(1) time (i.e. if a was an array, a[4]) and have a pre-set size at compile time. Linked lists have sequential access - to access an element, you have to loop through the list until you get to the element you want (i.e. if b was a linked list, to get to the 5th element of b you would have to iterate through elements 0, 1, 2, 3 and 4), and the size can be grown and shrunk dynamically.
Although there is nothing like a list in C per se but you sure could be talking about a linked lists implementation.
Array: Random access, predefine size.
Linked List: Sequential access, size at runtime.
Other languages like, say Python, may have have both lists and arrays inbuilt and their meaning may differ.
Useful comments from below:
You could add array lists. Lists which internally is an array which is doubled when needed and halved when only 1/4 full. This gives O(1) for add, remove, get(index) amortized. – lasseespeholt
Python's list is not a linked list. And the distinction between Python list and array is list can store anything while array can only store primitive types (int, float, etc). – KennyTM
For array, it has a fixed size like we write, new int [100]
but list does not have a fixed size...it can go on and on
Insertion and Deletion is easier in list than in array
Reason: we can simply use to change the pointers to insert and delete for linked list but for array insert and deletion needs shiftRight and shiftLeft
Linked List uses a dummy head node to avoid special cases of inserting into an empty list, or removing the last node from a list of unit size; and, it uses double links to allow iterating in both directions. The cost of course is the extra space needed to hold the dummy node (minimal cost), and the extra previous link in addition the usual next link for each node (much more significant cost).
In array, we can add with the help of its random access
In Linked list, reference to the tail node is simply header.prev, which gives us ability to append to the list in constant time (without having to iterate to find the tail reference, or having to maintain a separate tail reference).
But in array, we need to re-size the array before inserting.
Array has the flexibility to attain random access unlike Linked List.
Linked list has problems like,
It consumes extra memory storage for the pointer we are using!
Time complexity of O(n) instead of O(1) like in array
Reverse traversing is difficult for singly linked list and if we use doubly linked list, another pointer means more of extra memory storage
Heap Restriction as well! Memory is allocated only if there is space available in the heap. If insufficient memory then memory won't be created.
Array has problems like,
a chance of memory wastage or shortage.
Hope this helps ! :)
An often under appreciated characteristic of Linked data structures is that you can use them in situations where memory is highly fragmented due to there being no contiguous memory guarantee between elements. For example you could have 100MB of free space but only say a maximum run of free memory of length 10MB. In this case you can only create an an array of size 10MB but perhaps a potentially larger linked list since you would be able to make use of every run of free memory which was large enough to contain a single node.
array has only similar data types(i.e.,) they are homogeneous in nature. we can only have an array of strings , integers etc. also the size of array is predefined.
but in the case of list we can have any type of elements. let it be a string integer or combination of both.Also null or duplicate elements are allowed in list. example of list include arraylist , linkedlist.here in list the size can grow or shrink at any time.

Resources