The sorting seems to be working correctly. At least it sorts correctly :) It remains only to count the number of comparisons and swaps. How to calculate and output it?Somehow stalled at this point.. I will be very grateful for your help.If you demonstrate it with the updated code , I will be doubly grateful.
#include <stdio.h>
#include <stdlib.h>
void keyDown(int* arr, int n, int head)
{
int j;
if(2*head + 2 < n && arr[2*head + 1] < arr[2*head + 2])
{
j = 2*head + 2;
}
else j = 2*head + 1;
while(arr[head] < arr[j] && head < n / 2)
{
int tmp = arr[head];
arr[head] = arr[j];
arr[j] = tmp;
head = j;
if(2*head + 2 < n && arr[2*head + 1] < arr[2*head + 2])
{
j = 2*head + 2;
}
else j = 2*head + 1;
}
}
void heapSort(int* arr, int n)
{
int i;
for(i = n/2 - 1; i >= 0; i--)
{
keyDown(arr,n,i);
}
int l = n;
while(l > 1)
{
l--;
int tmp = arr[l];
arr[l] = arr[0];
arr[0] = tmp;
keyDown(arr,l,0);
}
}
int main(int argc, char *argv[]) {
int n=10;
int start, end,i;
int *arr;
arr=(int *)malloc(n*sizeof(int));
time_t invocation_time = time(NULL);
srand(invocation_time);
int s;
for (s=0;s<n;s++)
{
arr[s] = rand() % 50;
printf ("%d \n", arr[s]);
}
printf ("\n");
heapSort(arr, n);
for (i=0;i<n;i++){
printf ("%d \n", arr[i]);
}
return 0;
}
count the number of comparisons and swaps
make functions
//global counters
unsigned comparisons = 0, swaps = 0;
int lessthan(int a, int b) {
comparisons++;
return (a < b);
}
void swap(int *a, int *b) {
swaps++;
int tmp = *a; *a = *b; *b = tmp;
}
and then replace comparisons and swaps in your existing code with the specific function you need.
int main(int argc, char **argc) {
//...
if (lessthan(a[i], a[j])) swap(a+i, a+j);
//...
printf("comparisons: %u; swaps: %u\n", comparisons, swaps);
}
Related
This is my last try. I tried to find the most popular element in a string, for do this i've taken the string and converted single character in number and after this i sorted them in int array.
the problem is: when i use the 2d array for keep the frequency of each number: x[1][y]. and which number: x[0][y]. for some reason they are trash number
can someone help me?
(my english is rusty, sry).
#include<stdio.h>
#include<time.h>
#include<math.h>
#include<string.h>
#include<conio.h>
#include<ctype.h>
#include<stdlib.h>
#include<malloc.h>
void bubble(int a[],int x);
void frequenza(int A[], int n);
int main(){
size_t counter;
char a[] = "asrfujefwaa";
int b[20];
int x;
x = strlen(a);
for(counter = 0; counter != strlen(a); counter ++)
{
b[counter] = a[counter];
}
bubble(b,x);
for(counter = 0; counter != x; counter ++)
{
printf("%d ",b[counter]);
}
puts("\n");
system("pause");
puts("\n");
frequenza(b,x);
return 0;
}
void bubble(int a[],int x)
{
size_t i;
int ord;
int scambio;
scambio = 0;
if(ord == 1)
{
return;
}
else
{
ord = 1;
for(i = 0; i < x - 1; i++)
{
if(a[i] > a[i + 1])
{
scambio = a[i];
a[i] = a[i + 1];
a[i + 1] = scambio;
ord = 0;
}
}
bubble(a,x);
}
}
void frequenza(int A[], int n)
{
int x[2][n];
int z = 0;
int y = 0;
size_t q;
x[0][0] = A[0];
x[1][0] = 1;
for(z = 0; z != n; z++)
{
if(x[0][y] == A[z + 1])
{
x[1][y] += 1;
}
if(x[0][y] != A[z + 1])
{
y++;
x[0][y] = A[z + 1];
}
}
for(z = 0; z != 2; z++)
{
puts("\n");
for(q = 0; q != y;q++)
{
printf("%d ",x[z][q]);
}
}
}
If you want to find the most common character in a string, you don't need to sort it or anything fancy. Just iterate through the characters, recording how many times each one has been seen, and get the maximum such count. You can do it all with a single pass through the string if you keep track of the maximum to date as you go:
#include <limits.h>
#include <stdio.h>
int main(void)
{
char a[] = "asrfujefwaa";
int freqs[UCHAR_MAX + 1] = { 0 }; // Initialize frequency table to all 0's
int most_common = 0;
for (unsigned char *c = (unsigned char *)a; *c; c++) {
if (++freqs[*c] > freqs[most_common]) {
most_common = *c;
}
}
printf("Most common character is %c, with %d occurrences.\n",
most_common, freqs[most_common]);
return 0;
}
I'm trying to write an iterative function that computes all the permutations of an array of numbers given in input.
Here is the code I've written so far.
void permute(int *a, int size){
int j=0, i, h=0, m;
bool flag=true;
int f = factorial(size);
int *arr, *res;
int counter=0;
arr = malloc(f*sizeof(int));
for(i=0; i<f; i++)
arr[i] = 0;
while (j < f) {
if(arr[j]<j)
{
if(j%2 == 0)
{
swap(a[0],a[j]);
} else {
swap(a[arr[j]], a[j]);
}
arr[j]++;
j=0;
} else{
arr[j] = 0;
j++;
}
printf("%d\n",a[j] );
}
}
The code doesn't compute well all the permutations and goes into a long loop. Can someone help me, please? Thanks to everyone.
Your code is close but includes some problems. For instance, the while loop
while (j < f) will assign j to a value out of bound of the array a.
Instead would you please try:
#include <stdio.h>
#include <stdlib.h>
int factorial(int x)
{
int i;
int y = 1;
for (i = 1; i <= x; i++) {
y *= i;
}
return y;
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(int *a, int size)
{
int i, j = 0;
int f = factorial(size);
int *arr;
arr = calloc(f, sizeof(int)); // the members are initialized to 0
// print the original array
for (i = 0; i < size; i++) {
printf("%d%s", a[i], i == size - 1 ? "\n" : " ");
}
while (j < size) {
if (arr[j] < j) {
if (j % 2 == 0) {
swap(a + 0, a + j);
} else {
swap(a + arr[j], a + j);
}
// print the rearranged array
for (i = 0; i < size; i++) {
printf("%d%s", a[i], i == size - 1 ? "\n" : " ");
}
arr[j]++;
j = 0;
} else {
arr[j] = 0;
j++;
}
}
free(arr);
}
int main()
{
int a[] = {1, 2, 3}; // example
permute(a, sizeof a / sizeof a[0]); // the 2nd argument is the array length
return 0;
}
Output of the example:
1 2 3
2 1 3
3 1 2
1 3 2
2 3 1
3 2 1
What is the problem? Why is there always a fixed value of comparisons and swaps? And am I correct in counting swaps and comparisons in principle? I mean, do I accidentally count them in the wrong places? Maybe in some places it is not necessary to do this? Please help me because I really can't figure out what's wrong
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void mergeAbstract(int *a, int lb, int split, int ub, int *count, int *swaps)
{
int size = ub - lb + 1;
int *sub = (int *)malloc((ub + 1) * sizeof(int));
int i = 0, j = size - 1, k = lb;
int s;
for (s = 0; s < split + 1 - lb; s++) sub[s] = a[lb + s];
for (s = split + 1 - lb; s < size; s++) sub[s] = a[ub - (s - (split + 1 -lb))];
while (i <= j) {
(*count) += 2;
if (sub[i] > sub[j]) {
(*swaps)++;
a[k] = sub[j];
j--;
} else {
(*swaps)++;
a[k] = sub[i];
i++;
}
k++;
}
(*count)++;
free(sub);
}
void mergeSort(int *a, int lb, int ub, int *count, int *swaps) {
long split;
if (lb < ub) {
split = (lb + ub) / 2;
mergeSort(a, lb, split, count, swaps);
mergeSort(a, split + 1, ub, count, swaps);
mergeAbstract(a, lb, split, ub, count, swaps);
}
}
void arrprint(int *arr, int n) {
printf("%d", *arr);
int i;
for (i = 1; i < n; i++) printf(" %d", arr[i]);
puts("");
}
int main(int argc, char *argv[]) {
int n = 10;
int *arr = NULL;
arr = (int *)malloc(n * sizeof *arr);
int c = 0;
int *count = &c;
int h = 0;
int *swaps = &h;
srand(time(NULL));
int s;
for (s = 0; s < n; s++)
arr[s] = rand() % 50;
arrprint(arr, n);
mergeSort(arr, 0, n - 1, count, swaps);
arrprint(arr, n);
free(arr);
puts("");
printf("Comparison ans swaps : %d %d\n", *count ,*swaps);
return 0;
}
I made program that measure time of sorting n data arrays of int. Unfortunately my quicksort in worst case around 30000 numbers in array crashing program with return value 3221225725. For average case it works fine even for 500000 numbers (that is my max for testing).
Here is code for quicksort:
int part(int *tab, int left, int n)
{
int first = tab[left], i = left, j = n;
while (0 != 1)
{
while (tab[j] > first)
{
j--;
}
while (tab[i] < first)
{
i++;
}
if (i < j)
{
swap(&tab[i], &tab[j]);
i++;
j--;
}
else
return j;
}
}
void quick_sort(int *tab, int left, int n)
{
int pivot;
if (left < n)
{
pivot = part(tab, left, n);
quick_sort(tab, left, pivot);
quick_sort(tab, pivot + 1, n);
}
}
And here is code in for loop for data cases:
#include <stdio.h>
#include <stdlib.h>
#include "algorytmy.h"
#include <time.h>
int main(int argc, char *argv[]) {
srand(time(NULL));
int n;
clock_t czas1, czas2, czas3;
FILE *fw;
if (!(fw = fopen("danedowykresu_odwrotnie_zestaw2cd.txt", "w")))
{
printf("Blad otwarcia zbioru\n");
exit(2);
}
fprintf(fw,"Liczba danych;quicksort;shellsort;heapsort\n");
printf("Liczba danych;quicksort;shellsort;heapsort\n");
for(n = 25000; n < 500000; n += 1000)
{
int tab[n], i;
int *ptr = (int *)malloc(n * sizeof(int));
for (i = 0; i < n; i++)
ptr[i] = n - i;
czas1 = clock();
quick_sort(ptr, 0, n);
czas1 = clock() - czas1;
free(ptr);
for (i = 0; i < n; i++)
tab[i] = n - i;
czas2 = clock();
shell_sort(tab, n);
czas2 = clock() - czas2;
for (i = 0; i < n; i++)
tab[i] = n - i;
czas3 = clock();
heap_sort(tab, n);
czas3 = clock() - czas3;
fprintf(fw,"%d;%f;%f;%f\n", n, ((float)czas1) / CLOCKS_PER_SEC, ((float)czas2) / CLOCKS_PER_SEC, ((float)czas3) / CLOCKS_PER_SEC);
printf("%d;%f;%f;%f\n", n, ((float)czas1)/CLOCKS_PER_SEC, ((float)czas2) / CLOCKS_PER_SEC, ((float)czas3) / CLOCKS_PER_SEC);
}
fclose(fw);
return 0;
}
console screen
Your implementation is incorrect: it is unclear what you are testing with if (pocz < n). A pure implementation would test if (n - left > 1). The part() function has problems too: i and j are not properly initialized. It is always a good idea to verify correctness before even trying to measure performance.
The problem with quicksort worst case is you recurse too deep and eventually encounter a stack overflow.
Here is a modified version using a simple way to prevent deep recursion: only recurse on the smaller half and iterate on the larger one:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "algorytmy.h"
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int part(int *tab, int left, int n) {
int pivot = tab[left];
int i = left;
int j = n - 1;
for (;;) {
while (tab[i] < pivot)
i++;
while (tab[j] > pivot)
j--;
if (i < j) {
swap(&tab[i], &tab[j]);
i++;
j--;
} else {
return j + 1;
}
}
}
void quick_sort(int *tab, int left, int n) {
while (left + 1 < n) {
int p = part(tab, left, n);
if (p - left < n - p) {
quick_sort(tab, left, p);
left = p;
} else {
quick_sort(tab, p, n);
n = p;
}
}
}
int check_sorted(const int *ptr, int n, const char *name) {
for (int i = 1; i < n; i++) {
if (ptr[i - 1] > ptr[i]) {
printf("%s failed: ptr[%d] = %d > ptr[%d] = %d\n",
name, i - 1, ptr[i - 1], i, ptr[i]);
return 1;
}
}
return 0;
}
int main(int argc, char *argv[]) {
double czas1, czas2, czas3;
FILE *fw;
srand(time(NULL));
if (!(fw = fopen("danedowykresu_odwrotnie_zestaw2cd.txt", "w"))) {
printf("Blad otwarcia zbioru\n");
exit(2);
}
fprintf(fw,"Liczba danych;quicksort;shellsort;heapsort\n");
printf("Liczba danych;quicksort;shellsort;heapsort\n");
for (int n = 25000; n < 500000; n += 1000) {
int *ptr = malloc(n * sizeof(*ptr));
for (int i = 0; i < n; i++)
ptr[i] = n - i;
czas1 = clock();
quick_sort(ptr, 0, n);
czas1 = clock() - czas1;
check_sorted(ptr, n, "check_sorted");
for (int i = 0; i < n; i++)
ptr[i] = n - i;
czas2 = clock();
shell_sort(ptr, n);
czas2 = clock() - czas2;
check_sorted(ptr, n, "shell_sorted");
for (int i = 0; i < n; i++)
ptr[i] = n - i;
czas3 = clock();
heap_sort(ptr, n);
czas3 = clock() - czas3;
check_sorted(ptr, n, "heap_sorted");
fprintf(fw,"%d;%f;%f;%f\n",
n, czas1 / CLOCKS_PER_SEC, czas2 / CLOCKS_PER_SEC, czas3 / CLOCKS_PER_SEC);
printf("%d;%f;%f;%f\n",
n, czas1 / CLOCKS_PER_SEC, czas2 / CLOCKS_PER_SEC, czas3 / CLOCKS_PER_SEC);
free(ptr);
}
fclose(fw);
return 0;
}
I'm trying to make a merge sort algorithm in C. The problem is that it does not work for a big number of elements. If the array has 100000 elements it's OK but if it has 1e6 or 1e7 then it crashes. I thought that you cannot give such a big number of elements for an array but after I have read that this is not true, you should be able to give 1e7 elements. After that I thought that maybe int range is to small but that's not the case, int goes to 1e9. I don't really know what's the problem and why it doesn't work, so please help. Thanks in advance!
#include <stdio.h>
#include <stdlib.h>
int n;
void merge(int *, int, int);
void mergeSort(int *, int, int);
void bubbleSort(int *, int);
int main() {
// scanf("%d",&n);
n = 10000000;
int *a = (int *)malloc(n * sizeof(int));
if (a == NULL) {
printf("Nu s-a putut aloca memorie.");
exit(0);
}
for (int i = 0; i < n; i++)
a[i] = rand() % 50;
mergeSort(a, 0, n - 1);
//bubbleSort(a, n - 1);
// for (int i = 0; i < n; i++) {
// printf("%d ", a[i]);
// }
free(a);
return 0;
}
void merge(int *a, int start, int sfarsit) {
int mij = (start + sfarsit) / 2;
int i = start;
int j = mij + 1;
int k = start;
int aux[10000000];
while (i <= mij && j <= sfarsit) {
if (a[i] < a[j])
aux[k++] = a[i++];
else
aux[k++] = a[j++];
}
while (i <= mij)
aux[k++] = a[i++];
while (j <= sfarsit)
aux[k++] = a[j++];
for (int i = start; i <= sfarsit; i++)
a[i] = aux[i];
}
void mergeSort(int *a, int start, int sfarsit) {
if (start >= sfarsit)
return ;
int mij = (start + sfarsit) / 2;
mergeSort(a, start, mij);
mergeSort(a, mij + 1, sfarsit);
merge(a, start, sfarsit);
}
This:
int aux[10000000];
is problem. That will be to much for the stack to handle. Change to this:
int *aux = malloc(sizeof(*aux) * 10000000);
Of course, you need to use free(aux) in the end of the function merge and also check if the allocation was successful.
Also, you should of course allocate in relation to sfarsit but judging from your other code, it does not seem like I need to tell you that.
Your program has this problem: the definition int aux[10000000]; in the merge function defines a temporary array with automatic storage (aka on the stack) which is:
very large, potentially too large for your system, causing a stack overflow.
not necessary large enough if the array to be sorted is larger than 10 million elements.
You should allocate this temporary array, either locally in merge or in a wrapper function that would call mergesort with an extra argument.
It is also unnecessary and quite error prone to make n a global variable.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int mergeSort(int *a, int length);
void bubbleSort(int *, int);
int main() {
int n;
int *a;
n = 10000000;
//scanf("%d", &n);
if ((a = malloc(sizeof(*a) * n)) == NULL) {
printf("Nu s-a putut aloca memorie.");
return 1;
}
for (int i = 0; i < n; i++)
a[i] = rand() % 50;
mergeSort(a, n);
//bubbleSort(a, n);
for (int i = 1; i < n; i++) {
if (a[i] < a[i - 1]) {
printf("mergeSort failed\n");
break;
}
}
free(a);
return 0;
}
void merge(int *a, int start, int mij, int sfarsit, int *aux) {
int i = start;
int j = mij + 1;
int k = start;
while (i <= mij && j <= sfarsit) {
if (a[i] <= a[j])
aux[k++] = a[i++];
else
aux[k++] = a[j++];
}
while (i <= mij)
aux[k++] = a[i++];
while (j <= sfarsit)
aux[k++] = a[j++];
for (i = start; i <= sfarsit; i++)
a[i] = aux[i];
}
void mergeSortAux(int *a, int start, int sfarsit, int *aux) {
if (start >= sfarsit)
return;
int mij = (start + sfarsit) / 2;
mergeSortAux(a, start, mij, aux);
mergeSortAux(a, mij + 1, sfarsit, aux);
merge(a, start, mij, sfarsit, aux);
}
int mergeSort(int *a, int length) {
if (length > 1) {
int *aux = malloc(sizeof(*aux) * length);
if (aux == NULL)
return -1;
mergeSortAux(a, 0, length - 1, aux);
free(aux);
}
return 0;
}
Note that you can improve this code:
using size_t instead of int for the array sizes and index variables
using the convention start included and stop excluded, which avoids the +1/-1 adjustments.
by not copying the remaining values from the right slice as they are already in place in the original array.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int mergeSort(int *a, size_t length);
int main(int argc, char *argv[]) {
size_t n = 10000000;
int *a;
int res = 0;
if (argc > 1) {
n = strtoll(argv[1], NULL, 0);
}
if ((a = malloc(sizeof(*a) * n)) == NULL) {
printf("Nu s-a putut aloca memorie.");
return 1;
}
for (size_t i = 0; i < n; i++) {
a[i] = rand() % 50;
}
if (mergeSort(a, n)) {
printf("mergeSort failed: allocation error\n");
res = 1;
} else {
for (size_t i = 1; i < n; i++) {
if (a[i] < a[i - 1]) {
printf("mergeSort failed: out of order\n");
res = 1;
break;
}
}
}
free(a);
return res;
}
void merge(int *a, size_t start, size_t mid, size_t stop, int *aux) {
size_t i = start;
size_t j = mid;
size_t k = start;
while (i < mid && j < stop) {
if (a[i] <= a[j])
aux[k++] = a[i++];
else
aux[k++] = a[j++];
}
while (i < mid)
aux[k++] = a[i++];
for (i = start; i < k; i++)
a[i] = aux[i];
}
void mergeSortAux(int *a, size_t start, size_t stop, int *aux) {
if (stop - start >= 2) {
size_t mid = start + (stop - start) / 2;
mergeSortAux(a, start, mid, aux);
mergeSortAux(a, mid, stop, aux);
merge(a, start, mid, stop, aux);
}
}
int mergeSort(int *a, size_t length) {
if (length > 1) {
int *aux = malloc(sizeof(*aux) * length);
if (aux == NULL)
return -1;
mergeSortAux(a, 0, length, aux);
free(aux);
}
return 0;
}