LinkedList without dynamic memory allocation - arrays

Lets imagine that we are using development environment without dynamic memory (there are only static arrays with fixed bounds). How could one implement List (or ArrayList).
Well, I have idea of just cretaing new array of bigger size when I'm trying to add element to a full array, but I hope there is more efficient way.
P.S I'm not asking for implementation, I'm asking for ideas :)

You can check Sedgewick's document about dynamic arrays and resizing them. You can see the general idea in Dynamic Array - Wikipedia and a more detailed definition in this paper which is written by Sedgewick
Also there is a sample in ResizingArrayQueue by Sedgewick
Although, the example is used for the queues you can use this mechanism also for linkedlists.
In this sample he is doubling the size when it reaches the limit.
public void enqueue(Item item) {
// double size of array if necessary and recopy to front of array
if (N == q.length) resize(2*q.length); // double size of array if necessary
q[last++] = item; // add item
if (last == q.length) last = 0; // wrap-around
N++;
}
And when the limit decreases to the quarter of the array, he is halving the array.
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
Item item = q[first];
q[first] = null; // to avoid loitering
N--;
first++;
if (first == q.length) first = 0; // wrap-around
// shrink size of array if necessary
if (N > 0 && N == q.length/4) resize(q.length/2);
return item;
}

Related

Segregate Even and Odd numbers In an Integer Array using Recursion

I am doing an algorithm exercise, which asks to rearrange an array of integers, to put all the even-valued elements before odd-valued elements.
I thought for a while and came up with the following pseudo code:
int[] Rearrange(int [] arr)
{
if arr.length=1
return arr;
if arr[0] is even
return arr[0] followed by Rearrange(arr.subarray(1,arr.length))
else
return Rearrange(arr.subarray(1,arr.length)) followed by arr[0]
}
I am bit concerned about my proposed solution above, since I need to do a copy operation in each recursion cycle, which is expensive. Experts please kindly advise, thanks!
Recursion is expensive, and your approach would create tons of extra copies. Sometimes recursion yields an elegant solution, and other times it is absolutely the wrong tools for the job. This is a wrong-tool-for-the job case.
Instead, write a method that keeps a head index and a tail index. Initialize the head pointer to the beginning of the array and the tail index to the end.
At each pass, loop through the items at the head of the list, looking for odd values. When you find one, stop, then look for an even value from the end, looking backwards. When you find one, switch the two values (using a third int as temporary storage.) Repeat forever. When the head and tail indexes meet, you're done.
Something like this:
int head_index = 0;
int tail_index = array.count;
int temp;
while (true)
{
//Find the next odd number at the front of the array.
while (array[head_index] %2==0) && head_index < tail_index)
head_index++;
//Find the next even number at the end of the array.
while (array[tail_index]%2==1 && head_index < tail_index)
tail_index--;
//If the pointers meet, we're done
if (head_index <= tail_index)
break;
//Swap the items at the current indexes
temp = array[head_index];
array[head_index] = array[tail_index];
array[tail_index] = temp;
}
(Completely untested, and I'm tired, but the basic idea should work)
It's more-or-less C syntax pseudo code.
It should run in O(n) time, with the only extra RAM needed being your 2 indexes and the temporary holding variable.
Even though the question was answered, I'm putting the recursive version of solving this problem here so that people, who are wondering, can see why recursion is a bad approach for this problem.
public static int[] segregate(int[] array, int left) {
int leftIndex = left;
if(left == array.length) {
return array;
}
for(int i = leftIndex + 1; i < array.length; i++) {
if(array[leftIndex] % 2 == 1) {
if(array[i] % 2 == 0) {
int temp = array[leftIndex];
array[leftIndex] = array[i];
array[i] = temp;
}
}
}
return segregate(array, leftIndex + 1);
}
As can be seen from the code, the method will call itself N times. When you consider the fact that the complexity of for loop in the method is O(N), the total complexity of recursion will be O(n*2) which is worse than non-recursive solution.

How can I get a boolean out of a reiteration

I made this binary search using reiteration, however, when I get the answer (boolean), I seem to stumble in my way out of the reiteration and cant get the correct answer out of the function.
Can anybody help? Please comment on the code.
// binary search
bool
search(int value, int array[], int n)
{
// the array has more than 1 item
if (n > 1)
{
int m = (n/2);
// compares the middle point to the value
if (value == array [m])
return true;
// if the value given is lower than the middle point of the array
if (value < array [m])
{
int *new_array = malloc (m * sizeof(int));
// creating a new array with the lower half of the original one
memcpy(new_array, array, m * sizeof(int));
// recalling the function
search (value, new_array, m);
}
// if the value given is greater than the middle point of the array
else
{
int *new_array = malloc (m * sizeof(int));
// creating a new array with the upper half of the original one
memcpy(new_array, array + (m + 1), (m * sizeof(int)));
// recalling the function
search (value, new_array, m);
}
}
else if (n==1)
{
// comparing the one item array with the value
if (array[0] == value)
return true;
else
return false;
}
if (true)
return true;
else
return false;
}
You need to return the value of recursive searches.
return search (value, new_array, m);
Otherwise when you call search you are just throwing away the answer
You should return search(...);, and not only invoke the search() method - otherwise the return value is not bubbled up.
In addition, note that this algorithm is O(n) (linear in the size of the array) and is leaking memory and very inefficient, since you copy half of the array in each iteration.
Actually, It probably makes the algorithm much slower then the naive linear search for an element.
A good binary search does not need to copy half of the array - it just "looks" at half of it. It can be achieved by sending array+m as the array (for the higher half), and only decreasing n is enough for the lower half.
As mentioned by amint copying the array completely defeats the purpose of doing a binary search. Second, I believe you mean recursion, not reiteration.
Things to think about: Instead of copying the array, think about how you could achieve the same result by passing in a set of indexes to the array (like beginning and end).
As to your actual question, how to return the boolean value through the recursion. The thing about returning values out of a recursive function is that each iteration has to pass along the value. You can think of it like a chain of responsibility delegation. The first call is like the head of the company. He doesn't do all of the work, so he delegates it to his assistant but he does one piece of the work first. Then the assistant has an assistant etc. Turtles all the way down ;)
In order to get a value back though, each person in the chain has to give it back to the person before them. Going back to programming, this means that every time you recursively call search, you need to return that value.
Lastly, once you have those things in order you need to get your base case better defined. I assume that's what you're trying to do with
if (true)
return true;
else
return false;
However, as pointed out by H2CO3, this doesn't make much sense. In fact, your previous if statement if (n == 1) ... should make sure that the code after that is never executed.

Keeping Track of Array Indices which Meet Some Requirement in C

This sort of situation comes up pretty often. You loop through an array, and if some elements meet some requirement, you'd like to keep track of their indices for later. Here's what I mean:
for(i=0;i<10;++i)
{
if(array[i] > 10)
{
//Keep track of this index for later use.
}
}
The easy solution would be to create an array of 10 elements, and if say the 2nd element is greater than 10, one could do indices[i] = 1; But I feel this approach isn't that good. I'll need a large array to store this and most of the space is wasted.
In my application, I'm trying to find which bits are set in a bit array. So if bits 0 and 10 are set, I need to store these numbers for later use by the program. What's the best way to go about this?
This code needs to run on an AVR Mega and I'm using AVR-GCC so a C only solution is required.
You can use a bitmap: this only uses 1 bit per index, instead of 16 or 32 bits per index.
uint32_t bitmap[10] = {0}; // works for array size up to 320 elements
for(i=0;i<10;++i)
{
if(array[i] > 10)
{
//Keep track of this index for later use.
bitmap[i/32] |= (uint32_t)1 << (i%32);
}
}
for(i=0;i<10;++i)
{
if((bitmap[i/32] >> (i%32)) & 1)
{
// Later use :)
// Put some code here
}
}
On a PC, I would say a dynamically growing linked list or stack would be best.
On a microcontroller, it's often best to use statically allocated structures so that performance is deterministic and to avoid wasting precious memory. So a fixed size FIFO that stores the index you care about (rather than a simple 1/0 status) is the way to go. Just be prepared to think about detection and graceful failure if there's an overflow OR find some way to guarantee no overflow.
If you feel that much space would be wasted by using an additional array to remember the "special" indices, try to determine exactly how much space would be wasted. Then, use a smaller array. For example, if you know that you must remember at most 4 indices, declare an array of size 4.
You can also declare a small array, not large enough to remember all indices, and run the loop that fills it several times:
int indices[4];
int number_of_indices = 0;
int i_start = 0; // array entries up to this index were already checked
while (i_start < 10) {
for(i=i_start;i<10;++i)
{
if(array[i] > 10)
{
//Keep track of this index for "later use" below.
indices[number_of_indices++] = i;
// If 4 indices have been gathered, break the loop and use them
if (number_of_indices == 4)
{
break;
}
}
}
i_start = i;
// Put "Later use" here :)
// Do something for the list of indices gathered so far
}

Remove element from c array

I need to remove a specific element from an array, that array is dynamically resized in order to store an unknown number of elements with realloc.
To control the allocated memory and defined elements, I have two other variables:
double *arr = NULL;
int elements = 0;
int allocated = 0;
After some elements being placed in the array, I may need to remove some of them. All texts that I've found says to use memmove and reduce the variables by the number of elements removed.
My doubt is if this method is secure and efficient.
I think this is the most efficient function you can use (memcpy is not an option) regarding secured - you will need to make sure that the parameters are OK, otherwise bad things will happen :)
Using memmove is certainly efficient, and not significantly less secure than iterating over the array. To know how secure the implementation actually is, we'd need to see the code, specifically the memmove call and how return results from realloc are being checked.
If you get your memmove wrong, or don't check any realloc returns, expect a crash.
In principle, assuming you calculate your addresses and lengths correctly, you can use memmove, but note that if you overwrite one or more elements with the elements at higher indexes, and these overwritten elements were structs that contained pointers to allocated memory, you could produce leaks.
IOW, you must first take care of properly disposing the elements you are overwriting before you can use memmove. How you dispose them depends on what they represent. If they are merely structs that contain pointers into other structures, but they don't "own" the allocated memory, nothing happens. If the pointers "own" the memory, it must be deallocated first.
The performance of memmove() and realloc() can be increased by data partitioning. By data partitioning I mean to use multiple array chunk rather than one big array.
Apart from memmove(), I found memory swaping is efficient way. But there is drawback. The array order may be changed in this way.
int remove_element(int*from, int total, int index) {
if(index != (total-1))
from[index] = from[total-1];
return total-1; // return the number of elements
}
Interestingly array is randomly accessible by the index. And removing randomly an element may impact the indexes of other elements as well. If this remove is done in a loop traversal on the array, then the reordering may case unexpected results.
One way to fix that is to use a is_blank mask array and defer removal.
int remove_element(int*from, int total, int*is_valid, int index) {
is_blank[index] = 1;
return total; // **DO NOT DECREASE** the total here
}
It may create a sparse array. But it is also possible to fill it up as new elements are added in the blank positions.
Again, it is possible to make the array compact in the following efficient swap algorithm.
int sparse_to_compact(int*arr, int total, int*is_valid) {
int i = 0;
int last = total - 1;
// trim the last blank elements
for(; last >= 0 && is_blank[last]; last--); // trim blank elements from last
// now we keep swapping the blank with last valid element
for(i=0; i < last; i++) {
if(!is_blank[i])
continue;
arr[i] = arr[last]; // swap blank with the last valid
last--;
for(; last >= 0 && is_blank[last]; last--); // trim blank elements
}
return last+1; // return the compact length of the array
}
Note that the algorithm above uses swap and it changes the element order. May be it is preferred/safe to be used outside of some loop operation on the array. And if the indices of the elements are saved somewhere, they need to be updated/rebuilt as well.

How to remove an element found in an array and shift the array elements to the left?

int search(int a[]) {
int i,V,index;
printf("Enter the element (V),That you want to find:>");
scanf("%d",&V);
for (i=0;i<N;i++) {
if(a[i]==V) {
V=a[i];
index=i;
}
}
printf("%d is located in a[%d].",V,index
)
If you do not care about the ordering of the elements you can delete the found element in O(1) time.
// Find the element you're looking for.
int index = find(A, V);
// Stuff the last element into the index found.
A[index] = A[N-1];
// Reduce the total number of elements.
N--;
If I needed to move everything down the array, I'd use memmove(), carefully. And zap the vacated element with 0 or some other appropriate value.
if (index < N-1)
memmove(&a[index], &a[index+1], ((N-1)-index) * sizeof(a[0]));
array[N-1] = 0;
C arrays cannot be resized, so you cannot do this without creating a new array. Some suggestions you could implement:
Mark the item as deleted (lazy deletion) by either having a second deleted bool array or setting the item to some unused value such as -1.
Use vectors, but then this is not C anymore. STL vectors have an erase() method.
Vectors will be inefficient to delete from, so depending on the other operations you perform you could use a deque. Again, this then becomes C++, but you can also use erase() on a deque.
Perhaps use a linked list, binary tree or other data structure that allows you to quickly search for and remove nodes containing the target data.

Resources