I have this question in C language:
Implement the function: shift_element(int * arr, int i).
The function will get a pointer (not necessarily the beginning of the array) and the function will move the i next values to the right. Note that the function assumes that there is memory for at least i+1 cells after the pointer of the array.
Isn't it a swap function that I can use in Insertion sort? I don't understand the question properly. Thanks.
You can use memcpy:
void shift_element(int * arr, int i)
{
// moves i bytes from arr to arr + 1
memcpy(arr + 1, arr, i);
}
Description from the manual:
The memcpy() function copies n bytes from memory area src to memory
area dest. The memory areas must not overlap. Use memmove(3) if the
memory areas do overlap.
If you are to shift your elements, you don't actually need to sort them, nor even to swap a couple of them neither. As you said, you just need to move each element to the next place.
A regular loop should be enough, in which you'll simply do arr[index+1] = arr[index] but be careful to walk from right to left (having a loop starting from i and descending to 0), or you will clobber the elements you're about to move.
Please note that in most programming languages, a "shift" function generally does the opposite : shifting all elements to the left, returning the one at top of the list, then discarding it.
Related
I'm trying to implement quicksort in C.
I've done it before in Python, but I'm new to C and trying it out (please don't suggest I just use qsort()!)
What I don't understand is that since C doesn't handle arrays in the same way as Python, i.e. it can't pass them to and return them from functions, can only pass a pointer to one (or rather, the start of a space) in memory - how then can an array be used in a recursive function?
If my first call takes float array[], chooses a pivot, and sorts it. How can I then make successive calls for the lower and upper partitions, and glue them back together?!
Unless I'm mistaken, the glueing together requires an iteration through, since you can't assign to an array. But we can't do that, because we don't know how much memory we need on each call - and the spaces need to be different, because we still need the one higher (on earlier call)...
I've tried code, I've tried pen and paper, I just can't make this work - I understand recursion conceptually (and practically, in Python), I just can't see how to do this in C. I expect there's some functionality or syntax I just don't know about.
Grateful as ever.
As far as I know, most implementations of the Quicksort algorithm in C sort a given array
"in-situ", and do not return a new sorted array.
A very simple implementation that might be useful to understand the method is shown here:
http://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Quicksort#C
As you can see, the function just passes the same array with modified begin/end
index to the recursively called function.
Arrays decay into pointers to the first element when passed to a function,
so all recursively called functions operate on (a part of)
the same original array.
Other implementations might replace the recursion by iteration or tail-recursion,
see for example
Is stdlib's qsort recursive?
which has links to real-world implementations.
Python variables are accessed using a handle to the variable allowing Python to manage variables by knowing their size and the data type and whether the variable is in scope or not or in use or not for garbage collection. In C source code a variable represents an actual memory location.
An array variable in Python is a handle to an array which Python stores in memory along with information about the array such as its size (number of elements), the type of the data stored in the array, etc. In C an array variable is basically a constant pointer to some memory location that contains the array elements. However there is no management data stored along with the array. The only thing in the array's memory location is the data for the array elements. The information about the array's size, data type, etc. is lost after compiling the C source code and is not available at run time.
In Python you can cut and splice and copy array and array pieces because the information about the array is available at run time. In C it is not so simple because the information about the array is not available after the source code is compiled.
The problem faced by the designer of a generalized qsort() function is that it must have an interface that allows the function to be used with a wide variety of arrays. And since the information about the array is not available at run time with C, the programmer must ask for the minimum information needed to make the qsort() function work for a wide variety of arrays.
What the programmer needs to know is the following basic information: (1) where does the array start, (2) what is the size of each element of the array, (3) how many elements are in the array, and (4) what is the comparison function to be used to determine the collating sequence to determine the order of two elements of the array.
The array is sorted in place. What that means is that you pass to the qsort() function the array and when qsort() returns the elements of the array have been sorted. This sorting is done by selecting two elements, comparing them with the comparison function provided, and then if needed swapping the two array elements. Remember that in C an array is basically a constant pointer to an area of memory. So the qsort() function is provided that address, where the array starts, and the caller expects that the array starting at that memory location is sorted when qsort() returns.
Since the comparison function is provided by the user of qsort(), the person writing the comparison function knows what the array elements looks like. The programmer uses the pointers provided by the qsort() function when it calls the comparison function to access the two array elements and decide the order of those two elements returning an indication as to which is lower in the collating sequence.
However the swapping of array elements requires the use of a temporary data area which runs back into the problem of the qsort() function when written did not know the size of the array elements. So the swap is usually done a byte at a time.
The end result of all of the various constraints due to the memory model of C is that a qsort() function will use recursion by specifying array index or array offset from the beginning of the array. So the qsort() function performs the sort on a subsection of the array by specifying the beginning and ending indices of the subsection. What is changing during the recursive function calls is just the index values.
"The C Programming Language" has an implementation of qsort. I'll copy and paste the code directly:
void qsort(int v[], int left, int right) {
int i, last;
void swap(int v[], int i, int j);
int test = 100;
if (left >= right)
return;
swap(v, left, (left+right)/2);
last = left;
for(i = left+1; i <= right; i++)
if (v[i] < v[left])
swap(v, ++last, i);
swap(v, left, last);
qsort(v, left, last-1);
qsort(v, last+1, right);
}
The key here is that you specify the left and right bounds of the array with int left and int right that you want to process. That's how you deal with the "lower and upper partitions, and glue them back together" part you're confused with.
You call qsort initially with qsort(array,0,length-1), where length is the number of elements in array.
Why is it necessary to specify the number of elements of a C-array when it is passed as a parameter to a function (10 in the following example)?
void myFun(int arr[][10]) {}
Is it so because the number of elements is needed to determine the address of the cell being accessed?
Yes. It's because arr[i][j] means ((int *)arr)[i * N + j] if arr is an int [][N]: the pointer-arithmetic requires the length of a row.
The compiler needs to have an idea when the next row starts in memory (as a 2D array is just a continuous chunk of memory, one row after the other). The compiler is not psyche!
It is only necessary if you used static allocation for your array thought. Because the generate code create a continuous memory block for the array, like pointed out ruakh.
However if you use dynamic allocation it is not necessary, you only need to pass pointers.
Regards
I am trying to print a dynamic array, but I am having trouble with the bounds for the array.
For a simple example, lets say I'm trying to loop through an array of ints. How can I get the size of the array? I was trying to divide the size of the array by the size of the type like this sizeof(list)/sizeof(int) but that was not working correctly. I understand that I was trying to divide the size of the pointer by the type.
int *list
// Populate list
int i;
for(i = 0; i < ????; i++)
printf("%d", list[i]);
With dynamic arrays you need to maintain a pointer to the beginning address of the array and a value that holds the number of elements in that array. There may be other ways, but this is the easiest way I can think of.
sizeof(list) will also return 4 because the compiler is calculating the size of an integer pointer, not the size of your array, and this will always be four bytes (depending on your compiler).
YOU should know the size of the array, as you are who allocated it.
sizeof is an operator, which means it does its job at compile time. It will give you the size of an object, but not the length of an array.
So, sizeof(int*) is 32/62-bit depending on architecture.
Take a look at std::vector.
There is no standardized method to get the size of allocated memory block. You should keep size of list in unsigned listSize like this:
int *list;
unsigned listSize;
list = malloc(x * sizeof(int));
listSize = x;
If you are coding in C++, then it is better to use STL container like std::vector<>
As you wrote, you really did tried to divide the size of a pointer since list is declared as a pointer, and not an array. In those cases, you should keep the size of the list during the build of it, or finish the list with a special cell, say NULL, or anything else that will not be used in the array.
Seeing some of the inapropriate links to C++ tools for a C question, here is an answer for modern C.
Your ideas of what went wrong are quite correct, as you did it you only have a pointer, no size information about the allocation.
Modern C has variable length arrays (VLA) that you can either use directly or via malloc. Direcly:
int list[n];
and then your idea with the sizeof works out of the box, even if you changed your n in the mean time. This use is to be taken with a bit of care, since this is allocated on the stack. You shouldn't reserve too much, here. For a use with malloc:
int (list*)[n] = malloc(*list);
Then you'd have to adapt your code a bit basically putting a (*list) everywhere you had just list.
If by size you mean the number of elements then you could keep it in a counter that gets a ++ each time you push an element or if you dont mind the lost cycles you could make a function that gets a copy of the pointer to the first location, runs thru the list keeping a counter until it finds a k.next==null. or you could keep a list that as a next and a prev that way you wouldnt care if you lost the beginning.
I've an array, but I don't need its first (or last) position. So I point a new variable to the rest of the array, but I should free the array first/last position. For instance:
p = read_csv_file();
q = p + 1; // I don't need the first CSV file field
// Here I'd like to free only the first position of p
return q;
Otherwise I've to memcpy the array to other variable, excluding the first position, and then free the original array. Like this:
p = read_csv_file();
q = (int*) malloc(sizeof(int) * (SOME_SIZE - 1));
memcpy(q, p+1, sizeof(int) * (SOME_SIZE - 1));
free(p);
return q;
But then I'll have the overhead of copying all the array.
Is this possible to only free a single position of an array?
No. You can only free() a complete block obtained from a call to malloc() (or one of malloc()'s friends), not a piece of that block.
Your best bet is probably to leave the allocated block as-is and just use a pointer to the element at index one as if it were the beginning of the array (and ignore the last element).
Using memcpy works if it is really that important to free the two elements.
You could also shift all of the elements to the left by one (i.e., move the element at index one to index zero and so forth) and then call realloc() to resize the block and remove the last two elements. This isn't really a good idea, though, because the most likely outcome is that either (a) the underlying heap allocation won't actually be resized and you'll have moved thing around and gotten no benefit, or (b) the underlying heap allocation will be resized and everything will get moved a second time.
That is what realloc(3) is for. For releasing the first array element I'd suggest revising the algorithm.
I'm designing a recursive algorithm :
int f(int[] a, int[] b){
----changing a here
----changing b here
f(a,b)
----writing a here
----writing b here
}
I know all arrays are pointers so this code should be problematic. It'll write the final values of a and b after all the recursive calls finished. I dont want that to happen.
What should I do to pass that array to recursive calls as regular "pass by value"?
PS: Arrays may be dynamically allocated or resized etc anywhere in recursive calls.
I will assume that int f(int[] a, int[] b) is a typo: it should be int f(int a[], int b[]).
First of all, arrays and pointers are different. Under many circumstances, the name of an array "decays" to a pointer to its first element, but not always. Otherwise, sizeof a, for an array a wouldn't "work".
Secondly, let's ignore recursion for a moment. Let's also make the function prototype simpler:
int g(int *a);
(I changed int a[] to int *a, because in this context, the name of an array is equivalent to a pointer.)
Now, you say that you may "dynamically allocate or resize" the array in the function call. Since everything is passed by value in C, a dynamic allocation or resizing of a inside g() cannot be seen by the caller: the caller would still have the old value of a. But more importantly, if the "original" type of a was an array, i.e., the caller had code like:
int data[SIZE];
g(data);
then trying to resize data in g() is bad, because the parameter specified in the call wasn't dynamically allocated to begin with. You can only dynamically resize something that was the result of malloc(), calloc(), or realloc().
So, there are two problems even with this simple definition:
If g() has to dynamically resize the memory referred to by the address it is given, the value has to come from a dynamic allocation, not an array,
After fixing that, since g() wants to be able to signal the change to the caller, you need to pass a pointer to what needs to be changed. So, the prototype of g() becomes: int g(int **a);.
Hopefully the above will help you get started. If you tell us more about your algorithm, in particular, what you mean by: "changing" and "writing", you will get better responses.
Edit: to answer your question in the comment:
So when I passed an array to a function it decays to a pointer and this pointer is passed by value. If that pointer is pointing a place I allocated before that call...
If you allocated something before the call, it never was an array to begin with. It can be indexed as an array, but that's not the point. So, maybe you are getting confused by the terminology here?
...when my new function changes the pointed value then that value is changed at caller, too.
The pointed-to value is changed, yes.
I dont want it to be like this, so I need a copy of the pointed value in the new function so that my original pointer's pointed value would not change. am I clear now?
It's clearer now, but then that raises more questions:
If you are going to dynamically allocate or resize the data in each call to the function, how are you going to return those new pointers? You can't. And that means you have got yourself a memory leak. Unless you free() the data in the (recursively called) function itself.
How would you resize the pointer? You may not be able to know the size of the data pointed to, unless you use a sentinel value.
Are you using the function to iteratively solve a puzzle or a problem? Are you free()ing your data in each invocation of the function? If you can tell us, exactly what are you trying to do?
All arrays are not pointers.
See these:
http://c-faq.com/aryptr/practdiff.html
http://c-faq.com/aryptr/aryptrequiv.html
http://c-faq.com/aryptr/ptrkindofary.html - specifically this one
Assuming you want the order of the output to be the same as in your original, if you don't want the outer call to see changes to your arrays made in the recursive call, you need to copy them. The easiest way is probably to allocate them on the stack then memcopy from the argument, though that will cause a SO if it gets too big. The second easiest is to malloc and free them. You will probably need to pass the array size around too. You can't pass arrays by value on the stack in C.
Just print them before passing them to the next level of recursion.
Your question isn't terribly clear but what I'm reading is this:
You have a recursive algorithm that operates on two heap-allocated arrays. It is possible that one of the recursive calls will have to reallocate the arrays, and so when it returns to the next level up, the old pointers won't be valid anymore. You want to know how to "pass the arrays by value" in order to avoid this.
First, you cannot pass an array by value in C. Period. Arrays are always passed as pointers to the first element, and there's no way around that.
Second, the answer is always another level of indirection. :)
In order to solve the problem of having to reallocate the arrays during the recursive call, what you want to do is have the function take two pointer-to-pointers (int**), where *a gives the address of the pointer to the first element of the A array, and (*a)[n] gives the nth element of the a array. That way, you can reallocate the array to your heart's content, (changing the value of *a) but the value of a itself always remains the same. By doing this, instances of the function further up the call stack will automatically inherit the reallocations made by the recursive calls because the pointed-to value (*a) of the pointer (a) that they passed to the recursive call was modified to reflect the new location of the actual data.
e.g.
int f(int** a, int** b)
{
/* Do stuff on arrays using (*a)[n] and (*b)[n] */
if (some_condition) {
/* Time to reallocate */
*a = realloc(*a, new_size);
*b = realloc(*b, new_size);
}
/* Do stuff on arrays using (*a)[n] and (*b)[n] */
f(a, b); /* Recursive call */
/* Do more stuff using (*a)[n] and (*b)[n] */
/* a and b are still valid pointers, even though *a and *b might point somewhere new */
return foo;
}
void use_f(void)
{
int* a = malloc(starting_size);
int* b = malloc(starting_size);
f(&a, &b);
}
Given the requirements:
int f(int[] a, int[] b){
----changing a here
----changing b here
f(a,b)
----writing a here
----writing b here
}
What should I do to pass that array to recursive calls as regular "pass by value"?
PS: Arrays may be dynamically allocated or resized etc anywhere in recursive calls.
The code in f() is either authorized to make changes to the arrays (as now), or it is not authorized to make changes. If it is authorized to make changes, then there is nothing much you need to do, except worry about whether you are going to leak memory if you are using dynamic allocation.
If the code is not authorized to change the arrays, then it will have to make copies of the arrays. You can prevent the code from casually modifying them by including appropriate const qualifiers:
int f(const int *a, const int *b) { ... }
Note that you cannot pass arrays by value in C. You could have the caller pass a modifiable copy - or you can have the receiver (callee?) make the copy; one or the other will have to o so if the receiver is going to make modifications when it shouldn't.
The easiest and safest option is to pass a pointer and a size. Say you are working on something like quick-sort:
void sort_range( int* ptr, size_t count )
{
size_t pivot;
assert( ptr ); /* make sure we have memory */
if ( count < 2 ) return; /* terminate recursion */
pivot = partition( count ); /* select a pivot */
assert( pivot < count ); /* make sure we don't overrun the buffer */
sort_range( ptr, pivot ); /* sort left part */
sort_range( ptr + pivot, count - pivot ); /* sort right part */
merge( ptr, count, pivot ); /* merge ranges */
}
Always be conscious about size of the memory chunk you are working with. Unfortunately C doesn't make it easy, so you have to develop a habit of checking your memory ranges.