I am trying to create a function that will rearrange an array so it is in descending order. The array is made up from positive integers, with no two equal elements. This is what I have:
int check (int *v, int n){
int i;
for (i=0; i<n; i++){
if (v[i] != -1){
return -1;
break;
}
else return 1;
}
}
void sortVector (int *v, int n){
int i, k, j=0, vp[n];
while (check(v,n) == -1){
for (i=0; i<n; i++){
for (k=i+1; k<n; k++){
if (v[k] > v[i]) break;
else if (k == n-1){
vp[j] = v[i];
v[i] = -1;
j++;
}
}
}
}
for (i=0; i<n; i++)
v[i] = vp[i];
}
Which is not working correctly. I've been thinking about this for the past week so some pointers would be great. Thanks.
I tried to follow the idea that you have stated in your comment by starting from your code above and made few changes and here is the two final functions
#include <stdio.h>
int check (int *v, int n)
{
int i;
for (i=0; i<n; i++)
{
if (v[i] != -1)
{
return -1; // break is useless because return has the same effect
}
}
return 1; // you need to add a return here to handle all the cases
// the case if the loop is not entered you need to return a value
}
void sortVector (int *v, int n)
{
int i, k, j=0, vp[n];
int maxIndex=0;//you need to add this variable in order to keep track of the maximum value in each iteration
while (check(v,n) == -1)
{
for (i=0; i<n; i++)
{
maxIndex=i; //you suppose that the maximum is the first element in each loop
for (k=i+1; k<n; k++)
{
if (v[k] > v[maxIndex])
maxIndex=k; // if there is another element greater you preserve its index in the variable
}
//after finishing the loop above you have the greatest variable in the array which has the index stored in maxIndex
vp[i] = v[maxIndex]; // put it in vp array
v[maxIndex]=v[i];//put it in treated elements zone
v[i]=-1;// make it -1
j++;
}
}
for (i=0; i<n; i++)
v[i] = vp[i];
}
This is the test
int main()
{
int tab[]= {1,152,24,11,9};
sortVector (tab, 5);
int i=0;
for(i=0; i<5; i++)
{
printf("%d ",tab[i]);
}
return 0;
}
which gives the desired output
152 24 11 9 1
Note: You can improve your code by making swaps on the same array instead of allocating another array !
There are really lots of algorithms for sorting. A simple algorithm is to find the minimum element in your array and put it in the first position by swapping it with whatever item was in the first position and then recursively sorting the array but this time starting at the next position.
void sort(int a[], int l, int r)
{ if(l == r) return; /* 1-elemnt array is already sorted */
int min = l;
for(int i = l+1; i <= r; i++)
{ if(a[i] < a[min])
{ min = i;
}
}
swap(a[l], a[min]);
sort(a, l+1, r);
}
You can also do it iteratively.
Perhaps, the intention like following
int check (int *v, int n){
int i;
for (i=0; i<n; i++){
if (v[i] != -1){
return -1;
//break; //This code that does not reach
}
//else return 1; //move to after for-loop
}
return 1;
}
void ordenaVetor (int *v, int n){
int i, k, j=0, vp[n];
while (check(v,n) == -1){
for (i=0; i<n; i++){
if(v[i]<0) continue;//Element of -1 excluded. v[k] too.
for (k=i+1; k<n; k++){
if (v[k]>=0 && v[i] < v[k]) break;
}
if (k == n){
vp[j] = v[i];
v[i] = -1;
j++;
break;//start over
}
}
}
for (i=0; i<n; i++){
v[i] = vp[i];
}
}
You could use an existing sort implementation instead of reinventing the wheel:
#include <stdlib.h>
int desc(void const *a, void const *b)
{
if ( *(int *)a < *(int *)b ) return 1;
return -1;
}
void sortVector (int *v, int n)
{
qsort(v, n, sizeof *v, desc);
}
Related
This C code is for deleting all occurrences of an integer in an array. However, when I executed it, there is a problem with displaying the final array, the code doesn't display the rest of the array once it finds the first occurrence.
unsigned int T[10], n, i, j, exist, integerDeleteOccurences;
printf("Array length : ");
scanf("%u", &n);
for(i=0; i<n; i++)
{
printf("T[%u] : ", i);
scanf("%u", &T[i]);
}
for(i=0; i<n; i++)
{
printf("%u | ", T[i]);
}
printf("The number you want to delete its occurences : ");
scanf("%u", &integerDeleteOccurences);
exist = 0;
for (i=0; i<n; i++)
{
if (T[i] == integerDeleteOccurences)
{
j = i;
for (j=i; j<n-1; j++);
{
T[j] = T[j+1];
}
exist = 1;
i--;
n--;
}
}
if (exist == 1)
{
for (i=0; i<n; i++)
{
printf("%u | ", T[i]);
}
}
else if (exist == 0)
{
printf("This number doesn't exist in the array ! \n");
}
It is far to complicated.
size_t removeFromArray(int *arr, size_t size, int val)
{
int *tail = arr;
size_t newSize = size;
if(arr)
{
while(size--)
{
if(*tail == val) { tail++; newSize--;}
else
*arr++ = *tail++;
}
}
return newSize;
}
When working with statically allocated arrays (i.e. you know the maximum possible size), you should handle them by keeping track of their current size.
Here's a function that delete all occurrencies of an element, given an array and its size, and returns the number of deletions:
int deleteAllOccurrencies(int* arr, int size, int el)
{
int occurrencies = 0;
for (int i = 0; i < size; i++)
{
if (arr[i] == el)
{
occurrencies++;
// shift following elements
for (int j = i; j < size; j++)
{
arr[j] = arr[j + 1];
}
}
}
return occurrencies;
}
Edit with alternative solution (suggested by chqrlie)
The above function loops through an array of integers and for each occurrency found, removes the element from the array and shifts the following values by one position. However, that is not much efficient, since the time complexity of that approach is O(n²).
A better solution would be to loop through the array by using two indexes:
i, which is used to check each value in the starting array, and is increased at the end of each loop;
j, which is used to update only the array elements that are different from the one want to delete, and is increased only when that value is different.
This way we are able to get a much more efficient check, reaching a time complexity of O(n):
int deleteAllOccurrencies(int* arr, int size, int el)
{
int occurrencies = 0;
for (int i = 0, j = 0; i < size; i++)
{
if (arr[i] == el)
{
occurrencies++;
}
else
{
arr[j++] = arr[i];
}
}
return occurrencies;
}
Example Usage
#include <stdio.h>
#define MAX_SIZE 10
int deleteAllOccurrencies(int* arr, int size, int el);
void printArray(int* arr, int size);
int main(int argc, char** argv)
{
int array[MAX_SIZE] = { 1, 2, 3, 4, 2, 6, 7, 8, 2, 10 };
int size = MAX_SIZE, res;
printf("Array: ");
printArray(array, size);
res = deleteAllOccurrencies(array, size, 2);
size = MAX_SIZE - res;
printf("\nResult: %d occurrencies found!\n", res);
printf("Resulting array: ");
printArray(array, size);
return 0;
}
int deleteAllOccurrencies(int* arr, int size, int el)
{
int occurrencies = 0;
for (int i = 0, j = 0; i < size; i++)
{
if (arr[i] == el)
{
occurrencies++;
}
else
{
arr[j++] = arr[i];
}
}
return occurrencies;
}
void printArray(int* arr, int size)
{
printf("[ ");
for (int i = 0; i < size; i++)
{
printf("%d", arr[i]);
if (i < size - 1)
printf(", ");
}
printf("]\n");
}
#include <stdio.h>
void sort(int *ptr, int n) {
int i,j,tmp;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (ptr[i] < ptr[j])
{
tmp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=tmp;
}
}
int main() {
int i,n;
int *ptr;
printf("Nr. of elements : 5 \n");
n=5;
ptr=(int*)malloc( n * sizeof(int));
for (i=0;i<n;i++) {
scanf("%d",&ptr[i]);
}
printf("Initial array is : ");
for (i=0;i<n;i++) {
printf("%d ",ptr[i]);
}
sort(ptr,n);
printf("Sorted array is : ");
for (i=0;i<n;i++) {
printf("%d ",ptr[i]);
}
return 0;
}
This is my code. I'm trying to sort a pointer array using a function.
Whatever the (int) input, it sorts out fine.
My confusion is that i'm using
ptr[i] < ptr[j]
instead of
ptr[i] > ptr[j]
as it should normally be to sort it ascending.
Why is that?
No, your confusion is misplaced. Look at the for loops, and the relation between i and j. There are times when i < j and times when i > j, so what constitutes being "out of order" and requiring a swap?
The inner loop should start at i+1 not at '0'; that will make the relation between i and j invariant.
Given your loops go from i = 0 .. n and j = 0 .. n, there is no guarantee in your code that i < j.
There's two ways to fix this:
void sort(int *ptr, int n) {
int i,j,tmp;
for (i=0; i<n; i++) {
for (j=0; j<n; j++) {
if (i < j && ptr[i] < ptr[j]) { // Note the changed conditional
tmp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=tmp;
}
}
}
}
or
void sort(int *ptr, int n) {
int i,j,tmp;
for (i=0; i<n; i++) {
for (j=i+1; j<n; j++) { // Note the changed start value
if (ptr[i] < ptr[j]) {
tmp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=tmp;
}
}
}
}
As we can see, you are using bubble sort.
In bubble sort, our main intention is either transfer the heavier element to the end or lighter element to the top.
(ptr[i] < ptr[j])
what you are doing is moving the heavy elements to the end of the array, this is why whenever you are finding ptr[j](j is an inner loop variable) which is bigger than the ptr[i] (outer loop variable), you are doing a swap.
Hi there somehow my bubble sort that is suppose to work does not seem to work.Im not sure where the error is being caused.It is suppose to give me a sorted output list.It is giving me segmentation error and have been trying this for about 1 hr.Heres the code:
#include <stdio.h>
#include <stdlib.h>
#define N 10
void sort(int [], int);
void show(char *, int [], int);
int main(void)
{
int i, j, a[N];
srand(0);
for (j = 1; j <= 5; j++) {
// initialise array (pseudo-randomly)
for (i = 0; i < N; i++) {
a[i] = rand()%100;
}
// display, sort, then re-display
printf("Test #%d\n",j);
show("Sorting", a, N);
sort(a, N);
show("Sorted ", a, N);
}
return 0;
}
// sort array using bubble sort
void sort(int a[], int n)
{
int i, j, nswaps;
for (i = 0; i < n; i--) {
nswaps = 0;
for (j = n-1; j > i; j--) {
if (a[j] < a[j-1]) {
int tmp;
tmp = a[j];
a[j] = a[j-1];
a[j-1] = tmp;
nswaps++;
}
}
if (nswaps == 1) break;
}
}
// display array, preceded by label
void show(char *label, int a[], int n)
{
int i;
printf("%s:", label);
for (i = 0; i < n; i++) {
printf(" %02d", a[i]);
}
printf("\n");
}
Your are not technically sorting here.Instead of this for (i = 0; i < n; i--), try for (i = 0; i < n; i++).This is because you are starting with i=0 so in a FOR loop you need to increment i.
My code doesn't sort more than ten words and I need it to sort about 2000 strings of alfabet. and string length is less than 20 characters. I made sure that the file read and write is correct. the file have a list of words less than 20 characters and each line contains one word.
the problem is that the quick sort function is not sorting for large amount of strings.
#include <stdio.h>
#include <string.h>
void quickSortMain(char items[][20], int count);
void quickSort(char items[][20], int left, int right);
int main(void)
{
int i=0, n=0;
char str[2000][20];
memset(str, 0 , sizeof(str[0][0])*20*1000);
FILE *fil;
fil=fopen("text.txt","r");
if (fil!=NULL)
{
while (!feof(fil))
{
fgets(str[i], 20, fil);
i++;
}
fclose(fil);
}
else
{
printf("can not open");
scanf("\n");
}
fil=fopen("text.txt","w");
if (fil!=NULL)
{
fclose(fil);
}
else
{
printf("can not open");
scanf("\n");
}
quickSortMain(str, i);
fil=fopen("text.txt","a");
if (fil!=NULL)
{
while(n<i)
{
fprintf(fil,"%s", str[n]);
n++;
}
fclose(fil);
}
else
{
printf("can not open");
scanf("\n");
}
return 0;
}
void quickSortMain(char items[][20], int count)
{
quickSort(items, 0, count-1);
}
void quickSort(char items[][20], int left, int right)
{
int i=left;
int j=right;
char *x=items[(left+right)/2];
char temp[right+1];
while(i <= j)
{
while((strcmp(items[i],x) < 0) && (i < right)) {
i++;
}
while((strcmp(items[j],x) > 0) && (j > left)) {
j--;
}
if(i <= j) {
strcpy(temp, items[i]);
strcpy(items[i], items[j]);
strcpy(items[j], temp);
i++;
j--;
}
}
if(left < j) {
quickSort(items, left, j);
}
if(i < right) {
quickSort(items, i, right);
}
}
The problem is the pivot. When you swap the two elements in the innermost loop:
if(i <= j) {
strcpy(temp, items[i]);
strcpy(items[i], items[j]);
strcpy(items[j], temp);
i++;
j--;
}
one of those two elements, items[i], items[j], might be the pivot. In other words x might be pointing to one of them. After the swap, x isn't pointing to the correct pivot anymore, because the values in the elements to which x is pointing to were changed.
The simplest solution is to allocate additional space for the pivot:
...
char *x=items[(left+right)/2];
char pivot[20];
strcpy(pivot, x);
x = pivot;
...
I have other things to add to 2501's answer.
You should exit program when you detect you cannot read or write the file.
I would use strcpy() rather than memset() to initialize:
for (int n = 0; n < 2000; n++)
{
strcpy(str[n], "");
}
You poorly process newline characters. You should remove them from read lines in your array, and if you don't have one, you should write a warning and skip end of line, and after that add a newline after each word when you write your file. I tested your program and having 20 length lines or a last line with no newline at the end gives bad surprises.
your Quick sort implementation is wrong !!!
Here is a Quicksort for array in C-Programme
#include <stdio.h>
#include <stdlib.h>
int * quickSort(int *A,int pivotIndex, int N);
int partition(int *A, int pivotIndex, int N);
int main(){
int N;
printf("Enter Number of Elements : ");
scanf("%d",&N);
int A[N];
printf("\nEnter Data : ");
int i=0;
for(i=0; i<N; i++)
scanf("%d",&A[i]);
int *p;
p = quickSort(A,0,(N-1));
printf("\nSorted Data : ");
for(i=0; i<N; i++)
printf("%d ",p[i]);
return 0;
}
int * quickSort(int *A, int pivotIndex, int N){
if(pivotIndex < 0 || pivotIndex > N)
return ;
int q = partition(A,pivotIndex, N);
quickSort(A, 0, (q-1));
quickSort(A, (q+1), N);
return A;
}
int partition(int *A, int pivotIndex, int N){
int i = pivotIndex;
int flag = 0;
while(flag == 0){
flag = 1;
int j = N;
int rightFlag = 0, leftFlag = 0;
while(j > i && rightFlag == 0){
if(A[i]>A[j]){
int temp = A[i];
A[i] = A[j];
A[j] = temp;
i = j;
rightFlag = 1;
flag = 0;
}
j--;
}
if(flag == 1)
break;
flag = 1;
j = pivotIndex;
while(j < i && leftFlag == 0){
if(A[i]<A[j]){
int temp = A[i];
A[i] = A[j];
A[j] = temp;
leftFlag = 1;
flag = 0;
i = j;
}
j++;
}
}
return i;
}
This is a program which attempts to sort an array using the quick sort algorithm.
All seems to be fine, except that the output is not correct.
(Try the program for n=5, and then n=10. It works correctly for the former, but not the latter.)
#include <stdio.h>
//#include <iostream.h>
//#include <conio.h>
int partition(int arr[], int left, int right) {
int i = left, j = right;
int temp;
//Choosing the middle element as the pivot
//int pivot=arr[left];
int pivot = arr[(left+right)/2];
while (i <= j) {
while (arr[i] < pivot) {i++;}
while (arr[j] > pivot) {j--;}
if (i <= j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
return i;
}
void quick_sort(int arr[], int p, int r) {
if (p<r) {
int q=partition(arr, p, r);
quick_sort(arr, p, q-1);
quick_sort(arr, q+1, r);
}
}
int main() {
int values[100], n, i;
//clrscr();
printf("Enter no. of elements ");
scanf("%d", &n);
if (n>100) {
printf("Invalid input. Exiting now");
//getch();
return 0;
}
for (i=0; i<100; i++) values[i]=0;
printf("Enter the numbers\n");
for (i=0; i<n; i++) scanf("%d", &values[i]);
printf("The numbers you entered are\n");
for (i=0; i<n; i++) printf("%d ", values[i]);
printf("\n");
quick_sort(values, 0, n-1);
printf("Numbers after sorting are\n");
printf("(The output might not be the expected one (Be careful).\n");
for (i=0; i<n; i++) printf("%d ", values[i]);
//std::cin.get();
return 0;
}
There are two problems. First, the comparison i <= j is wrong. If i == j, you should not swap an element with itself. This should be changed to i < j in both places. Secondly, you should not move the i and j array indicies along after swapping. If it is the last swap, this pushes i past the actual pivot and causes your error.
int partition(int arr[], int left, int right) {
int i = left, j = right;
int temp;
//Choosing the middle element as the pivot
//int pivot=arr[left];
int pivot = arr[(left+right)/2];
while (i < j) {
while (arr[i] < pivot) {i++;}
while (arr[j] > pivot) {j--;}
if (i < j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
return i;
}
is better to use the std sort from algorithm.h :
http://www.cplusplus.com/reference/algorithm/sort/