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;
}
In array implementation of circular queue if we point front to a slot before the first element and rear to the last element, hen we face the problem of how to identify whether the queue is full or empty.
To solve this problem we use either a counter or waste one space in the buffer.
I was thinking of the following approach. Please correct me where I am going wrong, and if not please let me know if this is a better/worse solution than the above.
Point front to the first element and rear to the last element;
Have a function to check if the Queue has only 1 element left;
If we are dequeing the last element, make front and rear -1;
isEmpty() will be true if both front & rear are -1;
isFull will be true if front = (rear + 1) % size.
There is not much wrong logically with this approach. You are treating negative values in front and rear as a kind of flag to indicate the queue is empty. Assuming your logic to update front and rear keeps the values in the range 0..size, you only need to set one of them to be outside that range to indicate the queue is empty.
Consider this alternative. Many circular queues work with the front and rear indices as unsigned values, and the size as a power of 2. The updating of their values is always to increment, and they are allowed to wrap around. This avoids complicated logic to adjust those indices. Because the indices are unsigned, even if they wrap around, the difference arithmetic works properly to determine the number of elements.
The trick with the modulus working even if the indices wrap around on increment is that size is a power of 2. This ensures that the wrapping around does not affect the modulus computation.
unsigned front_ = 0, rear_ = 0;
Type q_[SIZE];
unsigned getCount () { return rear_ - front_; }
bool isEmpty () { return getCount() == 0; }
bool isFull () { return getCount() == SIZE; }
bool enQ (Type val) {
bool result = !isFull();
if (result) q_[rear_++ % SIZE] = val;
return result;
}
bool deQ (Type *val) {
bool result = !isEmpty();
if (result) *val = q_[front_++ % SIZE];
return result;
}
I was asked this question in an interview.The problem was i would be given a stack and have to find the element in the middle position of the stack."top" index is not available (so that you don't pop() top/2 times and return the answer).Assume that you will reach the bottom of the stack when pop() returns -1.Don't use any additional data structure.
Eg:
stack index
-----
2 nth element
3
99
.
1 n/2 th element
.
-1 bottom of the stack(0th index)
Answer: 1 (I didn't mean the median.Find the element in middle position)
Is recursion the only way?
Thanks,
psy
Walk through the stack, calculate the depth and on the way back return the appropriate element.
int middle(stack* s, int n, int* depth) {
if (stack_empty(s)) {
*depth = n;
return 0; //return something, doesn't matter..
}
int val = stack_pop(s);
int res = middle(s, n+1, depth);
stack_push(s, val);
if (n == *depth/2)
return val;
return res;
}
int depth;
middle(&stack, 0, &depth);
Note: yes, recursion is the only way. Not knowing the depth of the stack means you have to store those values somewhere.
Recursion is never the only way ;)
However, recursion provides you with an implied additional stack (i.e. function parameters and local variables), and it does appear that you need some additional storage to store traversed elements, in that case it appears that recursion may be the only way given that constraint.
"... Don't use any additional data structure. ..."
Then the task is unsolvable, because you need some place where to store the popped-out data. You need another stack for recursion, which is also a data structure. It doesn't make sense to prohibit any data structure and allow recursion.
Here is one solution: Take two pointers, advance one of them two steps at a time (fast), the other one only one step at a time (slow). If the fast one reaches the bottom return the slow pointer which points to the middle index. No recursion required.
int * slow = stack;
int * fast = stack;
while(1) {
if(STACK_BOTTOM(fast)) return slow;
fast--;
if(STACK_BOTTOM(fast)) return slow;
slow--;
fast--;
}
Recursion seems to be the only way. If you try to use the fast and slow pointer concept during popping, you will need to store the values somewhere and that violates the requirement of no additional data structure.
This question is tagged with c, so for the c programming language I agree that recursion is the only way. However, if first class anonymous functions are supported, you can solve it without recursion. Some pseudo code (using Haskell's lambda syntax):
n = 0
f = \x -> 0 # constant function that always returns 0
while (not stack_empty) do
x = pop
n = n+1
f = \a -> if (a == n) then x else f(a)
middle = f(n/2) # middle of stack
# stack is empty, rebuilt it up to middle if required
for x in (n .. n/2) do push(f(x))
Please note: during the while loop, there's no (recursive) call of f. f(a) in the else branch is just used to construct a new(!) function, which is called f again.
Assumed the stack has 3 elements 10, 20, 30 (from bottom to top) this basically constructs the lambda
(\a -> if a==1
then 30
else (\b -> if b==2
then 20
else (\c -> if c==3
then 10
else (\d -> 0)(c)
)
(b)
)
(a)
)
or a little bit more readable
f(x) = if x==1 then 30 else (if x==2 then 20 else (if x==3 then 10 else 0))
I've found the following code online,
int binary_search(int a[], int low, int high, int target) {
if (high < low)
return -1;
int middle = (low + high)/2;
if (target < a[middle])
return binary_search(a, low, middle-1, target);
else if (target > a[middle])
return binary_search(a, middle+1, high, target);
else if (target == a[middle])
return middle;
}
My function has a specified prototype(meaning that it has a set number of arguments that cannot be altered) this is what I have so far
bool search(int value, int array[], int n) {
if (array[n/2] == value)
return 1;
else if (array[n/2] < value)
return search(value, &array[n/2], (n)/2);
else
// how do I "return" the other half?
}
Does my implementation look correct so far? I can't seem to figure out how to implement the final else statement.
high and low represent the bounds of subarray in which continue the research. If you analyze the code you'll notice that if target is smaller that a[middle] you'll have to continue the research in the first half of the array (in fact it calls binary_search passing the same low bound but, as a superior bound, the actual middle-1). On the other side, if target is greater that a[middle] you'll have to continue the research in the second half of the array (from middle+1 to high). Of course, if target is equal to a[middle] you've finished.
The trick to writing a recursive anything:
Figure out how it should end.
Figure out how it should look one step before it ends.
Figure out how it should look two steps before it ends, and how moving from #2 to #1 is exactly the same as moving from #3 to #2.
Step #1:
If the number at the beginning of the search range is the desired number, return true.
If the end of the search range is the same as the beginning of the search range, and the number in the search range is not the desired number, return false.
Step #2:
If the search range has a length of two, split it into two one element search ranges, and search the range that might contain the required number.
Step #3:
If the search range has a length of more than two, split it into two roughly equal search ranges, and search the range that might contain the required number.
(which combining the two would look like)
If the search range has a length of two or more elements, split it into two roughly equal ranges, check the highest (last) number in the "lower" range, if the number is equal to or less than that number, search the lower range; otherwise, search the higher range.
This technique will not return you an optimum solution unless you select an optimum way to solve the problem; however, it will return you a correct solution (provided you do not make any true blunders).
Now the code
bool search(int value int array[], int lowIndex, int highIndex) {
if (array[lowIndex] == value) {
return true;
} else if (lowIndex == highIndex) {
return false;
}
int middleIndex = lowIndex + highIndex / 2;
if (array[middleIndex] <= value) {
return search(value, array, lowIndex, middleIndex);
} else {
return search(value, array, middleIndex+1, highIndex);
}
}
When reading code online, you have a big disadvantage. You don't do any of the above three steps, so you really have to go about solving the problem backwards. It is akin to saying, I have a solution, but now I have to figure out how someone else solved it (assuming that they didn't make any mistakes, and assuming that they had the exact same requirements as you).
The high and low variables represent the current range you are searching. You usually start with the beginning and end of the array, and then determine if the value is in the first or second half, or exactly in the middle. If it is in the middle, you return that point. If it is below the middle, you search again (recursively), but now only in the lower half. If it is above the middle, you search the upper half. And you repeat this, each time dividing up and narrowing the range. If you find the value, you return, otherwise, if the range is so narrow that it is empty (both low and end high indexes are the same), you didn't find it.
High and low are upper and lower bounds on the candidate indices of the array. In other words, they define the portion of the subarray in which it is possible for the search target to exist. Since the size of the subarray is cut in half each iteration, it is easy to see that the algorithm is O(log n).
return search(value, &array[(n)/2], (n)/2);
On your current code, first of all, n should not be in parentheses (it doesn't make a difference, but it confuses me).
Next up, if it's meant to be returning the index in the array, your code doesn't do that, it returns 1. Judging by the prototype, you might consider a non-recursive approach, but this can work fine if you add the right values on to each return.
You can figure out the other statement. Just draw a picture, figure out where the pointers should be, and code them up. Here's a start:
new array if > n/2
v-----------v
0, 1, 2, 3, 4, 5, 6, 7
^
n/2
Actually, you probably don't want to be including your middle value. Finally, make sure to take in to account lists of length zero, one, two and three. And please write unit tests. This is probably one of the most often incorrectly implemented algorithms.
I have tried to resolve your problem and this below code is really work . But what is the condition to escape recursion if value that want to be searched not lies in array
if(value==a[size/2]) return size/2;
if( value<a[size/2]) {
search(a,size/2,value);
} else if (value>a[size/2] && a[size/2]<a[(a.length-1)/2]) {
search(a,size/2+size,value);
} else {
search(a,size/2+a.length-1,value);
}
int * binSearch (int *arr,int size, int num2Search)
{
if(size==1)
return ((*arr==num2Search)?(arr):(NULL));
if(*(arr+(size/2))<num2Search)
return binSearch(arr+(size/2)+1,(size/2),num2Search);
if(*(arr+(size/2))==num2Search)
return (arr+(size/2));
return binSearch(arr,(size/2),num2Search);
}
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.