Issues with HeapSort [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
my task is to write the code to a heapsort according to pseudo code. It should heapsort the input Array (4 3 2 5 6 7 8 9 12 1) and then print it with the printHeap method. I know for a fact that the printHeap works, because I have already used it with a method called buildHeap (to build max heap binary trees, but you all already know that :)) and there it works flawlessly, so my problem lies in heapSort.
It sorts correctly and prints it in the way it's supposed to (parent -- child 1, parent -- 2, etc.), only issue is, that the biggest and last value, which is 12, suddenly turns into 24 and I have no clue why.
The code is the following:
void heapSort(int a[], int n){
int x = n+1;
int i;
int temp;
buildMaxHeap(a, n);
for (i = n; i >= 1; i--){
temp = a[i];
a[i] = a [0];
a [0] = temp;
x--;
heapify(a, 0, x);
}
void printHeap(int a[], int n){
int i;
printf("graph g { \n");
for (i = 0; i < n/2; i++){
printf("%d -- %d\n", a[i], a[left(i)]);
if (right(i) < n){
printf("%d -- %d\n", a[i], a[right(i)]);
}
}
printf("}\n");
Output is following:
1 2 3 4 5 6 7 8 9 24
graph g {
1 -- 2
1 -- 3
2 -- 4
2 -- 5
3 -- 6
3 -- 7
4 -- 8
4 -- 9
5 -- 24
}
just so you know what exactly I have done, I will attach the while .c file here:
https://onedrive.live.com/redir?resid=8BC629F201D2BC63!26268&authkey=!AFqVlm9AptiZ_xM&ithint=file%2cc
Really grateful for your help!
Cheers
Arik

Well, you observe an undefined behavior. (I personally on an online IDE got 0 instead of the 12(24).)
Try:
void heapSort(int a[], int n)
{
int x = n; /* changed from n+1 */
int i;
int temp;
buildMaxHeap(a, n);
for (i = n-1; i >= 0; i--){ /*<-- changed*/
temp = a[i];
a[i] = a[0];
a[0] = temp;
x--;
heapify(a, 0, x);
}
}
Your arrays in almost all general purpose languages of today start with index 0[For thorough information see wiki.] You loop your array for (i = n; i >= 1; i--) wrongly and since the heap is max, don't process the first element and go out of bounds with the last. Although arithmetic with the nth element is defined in the standard, it is not meant so rather < n and some pointer work.
On a side note, you can use macros (#defines) for the left, right etc. functions to improve performance and ease the reading.
I hope that saves the day and the AlgoDat Exercise.

Related

permutation of an integer without loops in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have to write a recursive function called permute that gets a int n and other parameters if needed, without using any loops. (no limitation on function's signature). I'm only allowed to call a printArray (or another assistance function) function from inside the permute function.
basically i thought of start printing the array (first output is 1 2 3) and for every digit i printed, note it (with a flag maybe, other ways would be appreciated). in the next row i will not print 2 for example because i raised a flag and when my flag will be raised i'll know that i have to make the swap.
my problems are how to use the flag properly, when to raise, how to take it down back. i'm not finding the flag way very useful here although i'm pretty sure its the best way.
any suggestions to fix my code would be appreciated. right now my output for input 3 is:
1 2 3
2 1 3
2 1 3
2 3 1
void permute (int arr[], int flagArr[], int size, int index){
int temp;
if (index == size - 1){
printf ("\n");
flagArr[index] = 0;
return;
}
else if (flagArr[index] == 1){
temp = arr[index];
arr[index] = arr[index + 1];
arr[index + 1] = temp;
flagArr[index] = 0;
print_array(arr, flagArr, 0, size);
permute (arr, flagArr, size, index+1);
}
else{
print_array (arr,flagArr, 0, size);
flagArr[index] = 1;
permute (arr,flagArr, size, index);
return;
}
}
void print_array (int arr[], int flagArr[], int index, int size){
if (index == size){
printf ("\n");
return;
}
else {
printf ("%d ",arr[index]);
print_array (arr, flagArr, index + 1, size);
}
}
for example: input 3 and the output should be:
All permutations of numbers (1 2 3):
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
UPDATE: no static variable and pointers allowed.

Correct way to write a pattern in C language [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I want to obtain the following output:
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10
The code am running is as follows:
#include <stdio.h>
int main(void) {
int i=1,flag=0,lines=0; //0 for forward, 1 for reverse
while(i!=0 && lines<3){
if(!flag){
printf("%d ",i);
if(i==10){
flag=1;
printf("\n");
lines++;
}
else
i++;
}
else if(flag){
printf("%d ",i);
if(i==1){
lines++;
flag=0;
printf("\n");
}
else
i--;
}
}
return 0;
}
Am getting the desired output from the above code but not sure if it's an optimal code. Any other method/suggestion? Considering unlimited space but time complexity should be kept minimum.
Condition: Use only one loop
Use forloops, minimize code that is repeated
#include <stdio.h>
int main(void) {
int lines, flag=1, val;
for(lines=0;lines<3;lines++)
{
if(flag == 1)
for(val=1;val<=10;val++)
printf("%d ", val);
else
for(val=10;val>0;val--)
printf("%d ", val);
printf("\n");
flag = -flag;
}
return 0;
}
Hint: you can use for loops to iterate in either direction:
for (int i = 1; i <= 10; ++i)
or
for (int i = 10; i >= 1; --i)
Also, a for loop is better than a while here because it really shows to the reader "I am iterating i from this to that."
Use an array and iterate it normally at first iteration, vice versa in the second iteration and then normally again.
Sample code:
#include <stdio.h>
#define SIZE 10
void print_arr(int* array, int size);
void print_rev_arr(int* array, int size);
int main(void)
{
int array[SIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int iter = 3;
for(int i = 0; i < iter; ++i)
if(i % 2)
print_arr(array, SIZE);
else
print_rev_arr(array, SIZE);
return 0;
}
void print_arr(int* array, int size)
{
for(int i = 0; i < size; ++i)
printf("%d ", array[i]);
printf("\n");
}
void print_rev_arr(int* array, int size)
{
for(int i = size - 1; i >= 0; --i)
printf("%d ", array[i]);
printf("\n");
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
IO completely dominates this problem.
But the fastest way to iterate forwards is
for(i=0;i<N;i++)
and the fastest and most elegant way to iterate backwards is
int i = N;
while(N--)
You can do this:
Use a for loop that will start from 1 and reach 10. Print its
counter.
Use a for loop that will start from 10 and stop at 1. Print its
counter.
Use a for loop that will start from 1 and reach 10. Print its
counter.
Sample code:
#include <stdio.h>
#define LEN 10
#define ITER 3
int main(void)
{
for(int i = 0; i < ITER; ++i)
{
if(i % 2)
for(int j = 1; j <= LEN; ++j)
printf("%d ", j);
else
for(int j = LEN; j >0; --j)
printf("%d ", j);
printf("\n");
}
return 0;
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
There are 2 things to consider.
First is whether the program is optimal or not. Is is quite easy to prove that your program is optimal (at least asymptotically optimal). You need to display 3n numbers, so you need at least 3n iterations. You have 3n iterations, so it's fine. You might be able to further optimize the iterations themselves, but that will arise as an implicit result of the second paragraph.
The second is readability. Your code is a bit verbose and unflexible. Consider the following:
int pattern[] = {1,2,3,4,5,6,7,8,9,10};
int patternSize = sizeof(pattern)/sizeof(int);
for (int i=0; i < 3; i++)
for (int j=0; j<patternSize; j++) {
if (i % 2)
printf("%d", pattern[patternSize - j - 1]);
else
printf("%d", pattern[i])
}
The code is shorter and clearer. Also, it is more maintable. It is clear what you have to do to chanelge the pattern. I could hardcode the pattern size as 10, but that would requite 2 changes when you change the pattern. I could generate the pattern, from the value of j, but that would limit the number of patterns that could be shown.
But what if the pattern is all the numbers from 1 to 200? Of course I'm not going to write them by hand. Just replace the array with a for loop that fills up the array. You don't have to change the code that displays the array. This is a small example of separation of concerns - one part of thr code does pattern generation, another part does the display, and they can be modified independently.
While this is asymptotically optimal, there are optimizations that can be made. For examples, using that array to store the pattern is not as efficient as generating the pattern from j. But in practice, unless more efficiency is needed, the advantages of this method outweigh the small performance penalty.
Okay, here's my take, I think it's more pleasant than most:
#include <stdio.h>
int main(void)
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 10; ++j)
{
const int v = (i % 2) ? 10 - j : j + 1;
printf("%d ", v);
}
putchar('\n');
}
return 0;
}
Some points:
Doesn't use an array, instead just generates the very simple pattern from the line number (i) and position (j).
Not designed for "pluggable" patterns by using an array, since the pattern was very simplistic and repeating, that is exploited to simplify the code.
Re-use the inner loop, rather than duplicating it.
Prints a linefeed in the proper place, to actually get separate lines (not all posted solutions to that).
The inner loop's body could be shortened to a single line by folding v into the printf() of course, but I aimed for readability and clarity, there.

Need help on an algorithm (stack overflow) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
This is a problem a friend of mine gave me as a challenge. I've managed to come up with a recursive algorithm that works fine for small inputs, however I get segmentation faults for large values. I suppose that's because of a stack overflow. I use the C language for solving the problem.
You are given an array of n numbers. Find and print the maximum length of the subset such that for any two numbers form that subset, the sum of the numbers is not divisible by k.
Input contains on the first line 2 numbers n and k, on the next line there are n numbers a[i] such that:
1 <= n <= 10^5
0 <= a[i] <= 10^9
1 <= k <= 100
# Example input:
4 3
1 7 4 2
# Output:
3
Explanation: (1 7 4) 1 + 7 = 8; 1 + 4 = 5; 7 + 4 = 11; all of them non-divisible by 3.
My solution is based on the following idea: For all numbers in the array check the sum with the others if it is divisible by k. If we find a match then create 2 arrays, one excluding the first term of the sum and one excluding the second one, this way we exclude such pairs from our subsets. Then do the same thing we did to the first array to both of them. If we have checked all the elements from the the array then set the solution to the length of the array and continue applying the "solver" to only the arrays that have a length greater than the solution already found. This algorithm works well for n < 47 , more than that and it gives me a seg fault. I would like to see any solution that solves the problem.
#include <stdio.h>
int n, k;
int * deleteElement(int * a, int n, int j){
int *c = (int*) malloc((n-1) * sizeof(int));
int k = 0;
for(int i = 0; i < n; i++){
if(i == j) continue;
c[k] = a[i];
k++;
}
return c;
}
int sol = 0;
void solver(int *a, int n, int *sol){
int *b, *c;
if(n <= *sol) return;
for(int i = 0; i < n-1; i++){
for(int j = i + 1; j < n; j++){
if((a[i] + a[j]) % k == 0){
c = deleteElement(a, n, i);
b = deleteElement(a, n, j);
solver(c, n-1, sol);
solver(b, n-1, sol);
return;
}
}
}
*sol = n;
}
int main(){
scanf("%d", &n);
scanf("%d", &k);
int a[n];
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
solver(a, n, &sol);
printf("%d\n", sol);
return 0;
}
You could use iteration to get rid of one of your two recursive calls, but that wouldn't help with stack space, since they have the same depth -- one call is as bad as 2.
It's easy enough to write a completely iterative algorithm that actually tests all the valid sets, but that's still an exponential time algorithm. In any case that this would save you from a stack overflow, it would take way too long to run. Since that algorithm would also suck, I don't want to write it.
A reasonable linear-time way to solve this problem is:
Calculate a map MODCOUNTS where MODCOUNTS[m] = the number of elements x such that x%k == m
Since any valid subset can only have one element divisible by k, if MODCOUNTS[0] > 1, then set MODCOUNTS[0]=1
Similarly, if k is even, and MODCOUNTS[k/2] > 1, then set MODCOUNTS[k/2]=1
Now, add up all the values in MODCOUNTS, but leave out a value MODCOUNTS[i] if:
i > 0, i*2 < k, AND MODCOUNTS[i] < MODCOUNTS[k-i]; OR
i*2 > k AND MODCOUNTS[i] <= MODCOUNTS[k-i]
rule 4 reflects that fact that a valid subset cannot include any elements x and y such that (x+y)%k = 0, for the cases that we didn't take care of in rules 2 and 3. The biggest valid subset includes all the elements from in MODCOUNTS[i], or all the elements in MODCOUNTS[k-i], but not elements from both.
If you use sparse data structure like a hash table to implement MODCOUNTS, then the whole thing takes O(N) time.

Bad exercise statement [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
Given the problem:
The statement is a bit ambiguous. I don't really understand what they want.
I can display the desired result using just a regular for loop:
int step = 0
for(int i = 1; i < m + 1; i++)
{
if(i != p)
{
printf("(%d, %d)", step, i);
step++;
}
}
Is this what they really want? I see that they are talking about linear time, so I think it can't be that easy? Am I supposed to build the vector that they are talking about, and then delete it?
Something like this? (compile with gcc test.c -lm)
#include <stdio.h>
#include <math.h>
int main(void) {
int i, j;
int n = 4;
int m = (int)pow(2,n);
int p = 5;
for(i = 1; i <= n; i++)
{
for(j = (int)pow(2,i-1); j < ((int)pow(2,i)); j++)
{
if(j == p) {
continue;
}
printf("%d, %d\n", i, j);
// remove vector[j]
if((j == (m-1)) && (m != p)) {
printf("%d, %d\n", i, m);
// remove vector[m]
}
}
}
return 0;
}
Run result n=3, p=5:
1, 1
2, 2
2, 3
3, 4
3, 6
3, 7
3, 8
Run result n=4, p=5:
1, 1
2, 2
2, 3
3, 4
3, 6
3, 7
4, 8
4, 9
4, 10
4, 11
4, 12
4, 13
4, 14
4, 15
4, 16
You should write the full code. Let me make it simple:
It should delete every element of the array.
By the end of the loop your program should print out the step and one of the numbers that were deleted, into the format (k, q) where k is the step you are on, and q is one of the elements you had deleted .
Every time you delete an element you can change it by X.
You also need to remember the algorithm they are telling you to use and the "rules of the game", for example: n should be positive and an integer.
And if you do not understand the algorithm, just try to put the idea on a paper:
When I put n = 1, I should delete one element from the array. When n = 2, 2 elements, When n = 3 it should delete 4 elements , n = 4 it deletes 8 element, etc.
As we can see, it is pretty simple because it goes like a geometric progression.

Sorting array of integers C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
i'm a beginner c programmer studying computer science and i'm trying to create a sorting program to sort an array of integers although i keep getting wrong results, this is what i got so far:
#include <stdio.h>
#include <string.h>
#define TAM 9
int sort_array(int num1[],int num2[]);
int main(){
int i=0;
int num1[TAM] = {5,6,2,4,7,1,3,0};
int num2[TAM] = {0};
int * ptr_num2 = num2;
sort_array(num1,num2);
while(*ptr_num2 != '\0'){
printf("%c",*ptr_num2+48);
ptr_num2++;
}
putchar('\n');
return 0;
}
int sort_array(int num1[],int num2[]){
int min=256,max=0,i,j;
int * ptr_num1 = num1;
int * ptr_max = num1;
int * ptr_num2 = num2;
/* check for max */
while(*ptr_max != '\0'){
if(*ptr_max > max) max = *ptr_max;
ptr_max++;
}
for(i=0;i<TAM-1;i++){
/* check for min */
for(j=0;j<TAM-1;j++){
if(*ptr_num1 < min) min = *ptr_num1;
ptr_num1++;
num1[i] = max;
}
*ptr_num2 = min;
ptr_num2++;
}
return 0;
}
I've been banging my head for several hours on this already.
EDIT: Forgot to mention that some of these things might not make sense since i'm just experimenting with a few things.
I understand you do not know about the typical array sorts... Well, let me to introduce you to one of the more simple ones. Allthough it's usually not the most efficient one, it's the easiest one to understand, and considering the fact you are messing with little arrays and not databases, it will be just fine.
I am talking about good old Chum, our Bubble sort.
Bubble sort is a well known simple array sorting algorithm -
The logic is simple. You go over the whole array on pairs of two - I.e, Array[0] with Array[1], Array[1] with Array[2], etc...
Whenever you find that things are not the way they are supposed to be - in your case, The larger index number is bigger than the lower index number - you swap between them, until you reach an iteration where you passed through the whole array and didnt swap at all.
In case you didn't understand well, here's Pseudo code from wikipedia (OMG who the heck uses wikipedia i'm such a n00b):
procedure bubbleSort( A : list of sortable items )
n = length(A)
repeat
swapped = false
for i = 1 to n-1 inclusive do
/* if this pair is out of order */
if A[i-1] > A[i] then
/* swap them and remember something changed */
swap( A[i-1], A[i] )
swapped = true
end if
end for
until not swapped
end procedure
And here's some C code:
#include <stdio.h>
int main()
{
int array[100], n, c, d, swap;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++)
scanf("%d", &array[c]);
for (c = 0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (array[d] > array[d+1]) /* For decreasing order use < */
{
swap = array[d];
array[d] = array[d+1];
array[d+1] = swap;
}
}
}
printf("Sorted list in ascending order:\n");
for ( c = 0 ; c < n ; c++ )
printf("%d\n", array[c]);
return 0;
}
Here again, btw, the credit is not for me:
http://www.programmingsimplified.com/c/source-code/c-program-bubble-sort
Hope this helped you, and good luck :)

Resources