Deleting occurrences of an element in an array in C - c

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");
}

Related

Print elements of an array that appear only once (C)

I am having trouble achieving the wanted results. The program should ask for 20 inputs and then go over each to see if they appear more than once. Then only print out those that appeared once.
However currently my program prints out random numbers that are not inputted.
For example:
array = {10,10,11,12,10,10,10.....,10} should return 11 and 12
#include <stdio.h>
void main() {
int count, size=20, array[size], newArr[size];
int number=0;
for(count = 0; count < size; count++) {
// Ask user for input until 20 correct inputs.
printf("\nAnna %d. luku > ", count+1);
scanf("%d", &number);
if( (number > 100) || (number < 10) ) {
while(1) {
number = 0;
printf("Ei kelpaa.\n");//"Is not valid"
printf("Yrita uudelleen > ");//"Try again >"
scanf("%d", &number);
if ( (number <= 100) && (number >= 10) ) {
break;
}
}
}
array[count] = number;
}
for(int i=0; i < size; i++) {
for(int j=0; j<size; j++){
if(array[i] == array[j]){
size--;
break;
} else {
// if not duplicate add to the new array
newArr[i] == array[j];
}
}
}
// print out all the elements of the new array
for(int k=0; k<size; k++) {
printf("%d\n", newArr[k]);
}
}
You don't need the newArr here, or the separate output loop. Only keep a count that you reset to zero at the beginning of the outer loop, and increase in the inner loop if you find a duplicate.
Once the inner loop is finished, and the counter is 1 then you don't have any duplicates and you print the value.
In code perhaps something like:
for (unsigned i = 0; i < size; ++i)
{
unsigned counter = 0;
for (unsigned j = 0; j < size; ++j)
{
if (array[i] == array[j])
{
++counter;
}
}
if (counter == 1)
{
printf("%d\n", array[i]);
}
}
Note that the above is a pretty naive and brute-force way to deal with it, and that it will not perform very well for larger array sizes.
Then one could implement a hash-table, where the value is the key, and the count is the data.
Each time you read a value you increase the data for that value.
Once done iterate over the map and print all values whose data (counter) is 1.
Use functions!!
Use proper types for indexes (size_t).
void printdistinct(const int *arr, size_t size)
{
int dist;
for(size_t s = 0; s < size; s++)
{
int val = arr[s];
dist = 1;
for(size_t n = 0; n < size; n++)
{
if(s != n)
if(val == arr[n]) {dist = 0; break;}
}
if(dist) printf("%d ", val);
}
printf("\n");
}
int main(void)
{
int test[] = {10,10,11,12,10,10,10,10};
printdistinct(test, sizeof(test)/sizeof(test[0]));
fflush(stdout);
}
https://godbolt.org/z/5bKfdn9Wv
This is how I did it and it should work for your:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <stdarg.h>
void printdistinct(const int *muis, size_t size);
int main()
{
int loop=20,i,muis[20],monesko=0;
for(i=0; i<loop; i++){
monesko++;
printf ("Anna %d. luku: \n",monesko);
scanf("%d", &muis[i]);
if (muis[i]<10 || muis[i]>100){
printf("Ei kelpaa!\n");
muis[i] = muis[i + 1];
printf("YRITÄ UUDELLEEN:\n ");
scanf("%d", &muis[i]);
}
}
printdistinct(muis, sizeof(muis)/sizeof(muis[0]));
fflush(stdout);
return 0;
}
void printdistinct(const int *muis, size_t size)
{
for(size_t s = 0; s < size; s++)
{
int a = muis[s];
int testi = 1;
for(size_t n = 0; n < size; n++){
if(s != n) {
if(a == muis[n]){
testi = 0;
break;
}
}
}
if(testi) {
printf("%d \n", a);
}
testi = 1;
}
printf("\n");
}
This approach uses some memory to keep track of which elements are duplicates. The memory cost is higher, but the processor time cost is lower. These differences will become significant at higher values of size.
char* duplicate = calloc(size, 1); // values are initialized to zero
for (unsigned i = 0; i < size; ++i)
{
if(!duplicate[i]) // skip any value that's known to be a duplicate
{
for (unsigned j = i + 1; j < size; ++j) // only look at following values
{
if (array[i] == array[j])
{
duplicate[i] = 1;
duplicate[j] = 1; // all duplicates will be marked
}
}
if (!duplicate[i])
{
printf("%d\n", array[i]);
}
}
}
What you can do is you can initialize a hashmap that will help you store the unique elements. Once you start iterating the array you check for that element in the hashmap. If it is not present in the hashmap add it to the hashmap. If it is already present keep iterating.
This way you would not have to iterate the loop twice. Your time complexity of the algorithm will be O(n).
unordered_map < int, int > map;
for (int i = 0; i < size; i++) {
// Check if present in the hashmap
if (map.find(arr[i]) == map.end()) {
// Insert the element in the hash map
map[arr[i]] = arr[i];
cout << arr[i] << " ";
}
}

How can I avoid using globals?

I have this program that I try to run:
void get_set(int size, int arr[])
{
int i;
printf("Enter number of values to the array : \n");
scanf("%d", &size);
printf("\n");
for (i = 0; i < size; i++)
{
printf("Value at %dth place is : \n", i + 1);
if (scanf("%d", &arr[i]) == EOF)
{
break;
}
}
}
void print_set(int size, int arr[])
{
int i, flag = 0;
if (flag == 0)
{
printf("\nOriginal array is : ");
for (i = 0; i < size; i++)
{
printf("%d,", arr[i]);
}
printf("\n");
}
else
{
printf("\nArray after deleting duplicates : ");
for (i = 0; i < size; i++)
{
printf("%d,", arr[i]);
}
printf("\n");
}
flag + 1;
}
void RemoveDuplicates(int size, int arr[])
{
int i, j, k;
for (i = 0; i < size; i++)
{
for (j = 0; j < i; j++)
{
if (arr[i] == arr[j])
{
size--;
for (k = i; k < size; k++)
{
arr[k] = arr[k + 1];
}
i--;
}
}
}
}
int main()
{
int size = 0;
int arr[64] = {0};
get_set(size, arr);
print_set(size, arr);
RemoveDuplicates(size, arr);
print_set(size, arr);
return 0;
}
In short, the program gets an array with values that I entered, and passes it thru other functions.
I can't get it to pass the array and size to other functions. I am trying to avoid globals; what am I doing wrong?
The size variable in main is passed by value to get_set, so it will still be 0 in main. You should have get_set return the size and assign the result to the size variable (or pass size by reference) so that you can pass it to print_set and RemoveDuplicates.
get_set doesn't really need size as a parameter, unless you change it's meaning to indicate the capacity of the array and add error checking to make sure that you don't overflow it.
The arr variable is passed by reference because it is an array which decays into a pointer, so get_set will modify the variable in main.
You could use:
#include <stdio.h>
#include <stdlib.h>
static int get_set(int size, int arr[])
{
int i;
int n;
printf("Enter number of values to the array: ");
fflush(stdout); // Usually not strictly necessary, but ensures the prompt appears
if (scanf("%d", &n) != 1)
{
fprintf(stderr, "Invalid number entered\n");
exit(EXIT_FAILURE);
}
if (n > size)
n = size;
printf("\n");
for (i = 0; i < n; i++)
{
printf("Value %d is: ", i + 1);
fflush(stdout);
if (scanf("%d", &arr[i]) != 1)
{
break;
}
}
return i;
}
static void print_set(const char *tag, int size, int arr[])
{
int i;
printf("\n%s: ", tag);
for (i = 0; i < size; i++)
{
printf("%d,", arr[i]);
}
printf("\n");
}
static int RemoveDuplicates(int size, int arr[])
{
int i, j, k;
for (i = 0; i < size; i++)
{
for (j = 0; j < i; j++)
{
if (arr[i] == arr[j])
{
size--;
for (k = i; k < size; k++)
{
arr[k] = arr[k + 1];
}
i--;
}
}
}
return size;
}
int main(void)
{
int arr[64] = {0};
int size = get_set(64, arr); // 64 is the maximum; size contains the actual
print_set("Original array", size, arr);
size = RemoveDuplicates(size, arr);
print_set("Duplicates removed", size, arr);
return 0;
}
None of the functions except main() are called from outside this file; the functions can all be static, therefore.
Example run:
Enter number of values to the array: 12
Value 1 is: 1
Value 2 is: 1
Value 3 is: 1
Value 4 is: 2
Value 5 is: 2
Value 6 is: 3
Value 7 is: 4
Value 8 is: 5
Value 9 is: 99
Value 10 is: 999
Value 11 is: 1
Value 12 is: 1
Original array: 1,1,1,2,2,3,4,5,99,999,1,1,
Duplicates removed: 1,2,3,4,5,99,999,
An alternative redesign of the print_set() function would make the flag in the original code into a static int. However, that is a far less flexible solution than passing the tag string argument to the function. Static variables inside functions are occasionally useful, but they should be regarded with a jaundiced eye and avoided when possible, just as global variables should be avoided when possible.

Creating a new array without duplicate integers from an array in C

I was asked to create a new array without duplicate integars from an array.
I think I made a mistake in my code but can't notice anything wrong.
The output for "1, 2, 1, 2, 1, 4" is "1, 2, 2, 4".
It's supposed to be "1, 2, 4"
Would like to learn about my mistake.
// Exercise 2 -
void Ex2() {
int i, counter = 1, size = -1;
int* array = input_dynamic_array(&size);
int* newArr = (int*)malloc((size)* sizeof(int));
newArr[0] = array[0];
assert(array);
for (i = 1; i < size; i++) {
if (!find_num_in_newArr(newArr, size, array[i])) {
newArr[counter++] = array[i];
}
}
newArr = (int*)realloc(newArr, (counter)*sizeof(int));
printArray(newArr, counter);
free(array);
free(newArr);
}
bool find_num_in_newArr(int *newArr, int size, int num) {
int i;
for (i = 0; i < size; i++) {
if (newArr[i] == num) {
return true;
}
return false;
}
}
int* input_dynamic_array(int *size)
{
int *array;
int ii;
printf("Enter array size: ");
scanf("%d", size);
array = (int*)malloc((*size) * sizeof(int));
assert(array);
printf("Enter %d integer numbers: ", *size);
for (ii = 0; ii < *size; ii++)
scanf("%d", array + ii);
return array;
}
I see a problem here:
for (i = 0; i < size-1; i++)
{
if (newArr[i] == num)
{
return true;
}
return false;
}
This will never have another iteration. It will either return true or false from the first iteration. Thats not what you are planning for when you used a loop.
Based on your design, you might want to move return false; outside the loop.
Another advise, Don't cast the return value of malloc, its pointless.
Also,
int* newArr = (int*)malloc((size)* sizeof(int));
This needs to be followed by a check. You need to check if malloc returned NULL. If yes, then memory is not allocated and anything with modification based on newArr would be horrible.
A relative cleaner way of doing it will include using a function that looks like below:
int RemoveDuplicates(int* Arr, int length)
{
int i = 0, j = 0;
int LengthChanged = 0;
for (i = 1; i < length; i++)
{
for(j = 0; j < LengthChanged ; j++)
{
if(Arr[i] == Arr[j])
break;
}
// Copy as is if there is not duplicate element in the array
if (j == LengthChanged )
Arr[LengthChanged++] = Arr[i];
}
return LengthChanged;
}
There are 2 problems in your code:
find_num_in_newArr exits the loop with a return false; at the first iteration. move the return statement outside the loop body.
Ex2 check the whole array for duplicates instead of just the portion already copied: find_num_in_newArr(newArr, size, array[i]) should be find_num_in_newArr(newArr, i, array[i]). As posted, this code has undefined behavior.
Here is a corrected version with a few extra assertions:
// Exercise 2 -
bool find_num_in_newArr(const int *newArr, int size, int num) {
int i;
for (i = 0; i < size; i++) {
if (newArr[i] == num) {
return true;
}
}
return false;
}
int *input_dynamic_array(int *size) {
int *array;
int ii;
printf("Enter array size: ");
assert(scanf("%d", size) == 1);
assert(*size > 0);
array = (int*)malloc((*size) * sizeof(int));
assert(array != NULL);
printf("Enter %d integer numbers: ", *size);
for (ii = 0; ii < *size; ii++) {
assert(scanf("%d", array + ii) == 1);
}
return array;
}
void Ex2(void) {
int i, counter, size;
int *array = input_dynamic_array(&size);
int *newArr = (int*)malloc(size * sizeof(int));
assert(newArr != NULL);
newArr[0] = array[0];
counter = 1;
for (i = 1; i < size; i++) {
if (!find_num_in_newArr(newArr, i, array[i])) {
newArr[counter++] = array[i];
}
}
newArr = (int*)realloc(newArr, counter * sizeof(int));
assert(newArr != NULL);
printArray(newArr, counter);
free(array);
free(newArr);
}
You over complicate it a bit.
Use the correct types for the indexes (size_t)
int CheckValue(int *arr, int value, size_t size)
{
while (size--)
{
if (arr[size - 1] == value) return -1;
}
return 0;
}
int main()
{
int arr[] = {1,4,5,8,3,2,1,-1,9,-1,-1,6,8,1,5,4,2,3};
int newarr[sizeof(arr) / sizeof(arr[0])];
size_t size = 0;
for (size_t index = 0; index < sizeof(arr) / sizeof(arr[0]); index++)
{
if (!CheckValue(newarr, arr[index], size))
{
newarr[size++] = arr[index];
}
}
return 0;
}

Swapping largest and smallest numbers in C

I want to write a program that reads 10 int values from the user and swaps the largest and smallest numbers on the first and second values, then the rest of the numbers should be in the order.
Please check the code and help me what the wrong is.
For instance:
1
9
4
5
6
7
8
2
4
5
New order should be 9 1 4 5 6 7 8 2 4 5
#include <stdio.h>
int main() {
int a[10],i,min,max=0,pos=0;
printf("Please enter 10 int values :\n");
do{
scanf("%d", &a[pos++]);
} while (pos<10);
for (i=0; i<10;i++) {
printf("%i\n",a[i]);
if (max<a[i])
{
max=a[i];
}
if (min>a[i])
{
min=a[i];
}
for (i=0;i<10;i++) {
if (a[i]==max)
a[i]=max;
if (a[i] == min) a[i] = min;
}
printf("The new order is : %d %d %d ", max, min, ...);
return 0;
}
EDIT:
It is the new form
#include <stdio.h>
int main() {
int a[10],i,pos,temp,min = 0,max = 0;
printf("Please enter 10 int values :\n");
do {
scanf("%d", &a[pos++]);
} while (pos < 10);
for ( =1; i<10;i++) {
if (a[i]>a[max])
{
max=i;
}
if (a[i]<a[min])
{
min=i;
}
}
temp=a[max];
a[max]=a[min];
a[min]=temp;
printf("%d %d",a[max],a[min]);
for (i=0;i<10;i++){
if ((i != min) && (i != max)) {
printf("%d ", a[i]);
}
}
printf("\n");
return 0;
}
As others have noted, your code does not properly identify the maximum and minimum values in the array because you are writing min and max back into the array instead of the other way around.
Since you want to swap these values, what you actually want are the indices of the min and max values of the array, and swap those.
It is best to break this code into functions instead of having everything in main. Here is a solution that will do what you want:
#include <stdio.h>
int indexofmax(int *data, int len)
{
int max = 0;
int i;
for(i = 0; i < len; i++)
{
if(data[i]>data[max]) max = i;
}
return max;
}
int indexofmin(int *data, int len)
{
int min = 0;
int i;
for(i = 0; i < len; i++)
{
if(data[i]<data[min]) min = i;
}
return min;
}
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
// user enters in 10 ints...
int max = indexofmax(a, 10);
int min = indexofmin(a, 10);
int i;
swap(&a[min], &a[max]);
for(i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
return 0;
}
This initialization min=0,max=0 is not right.
Instead have min = INT_MAX and max = INT_MIN.
By setting min=0, you would never get the lowest number in the array if it is greater than 0.
Similarly by setting max=0, you would never get the greatest number in the array if it is lower than 0.
You are gaining nothing by this code:
for(i=0;i<10;i++)
{ if(a[i]==max) a[i]=max;
if(a[i]==min) a[i]=min; }
It is evident that this loop
for(i=0;i<10;i++)
{ if(a[i]==max) a[i]=max;
if(a[i]==min) a[i]=min; }
does not make sense.
Moreover variable min is not initialized while variable max is initialized incorrectly.
int a[10],i,min,max=0,pos=0;
For example the array can contain all negative elements. In this case you will get incorrect value of the maximum equal to 0.
And I do not see where the elements are moved to the right to place the maximum and the minimum to the first two positions of the array.
If I have understood correctly then what you need is something like the following. To move the elements you could use standard function memmove declared in header <string.h>. However it seems you are learning loops.
#include <stdio.h>
#define N 10
int main( void )
{
int a[N] = { 4, 5, 9, 6, 7, 1, 8, 2, 4, 5 };
for (size_t i = 0; i < N; i++) printf("%d ", a[i]);
printf("\n");
size_t min = 0;
size_t max = 0;
for (size_t i = 1; i < N; i++)
{
if (a[max] < a[i])
{
max = i;
}
else if (a[i] < a[min])
{
min = i;
}
}
if (max != min)
{
int min_value = a[min];
int max_value = a[max];
size_t j = N;
for (size_t i = N; i != 0; --i)
{
if (i - 1 != min && i - 1 != max)
{
if (i != j)
{
a[j - 1] = a[i - 1];
}
--j;
}
}
a[--j] = min_value;
a[--j] = max_value;
}
for (size_t i = 0; i < N; i++) printf("%d ", a[i]);
printf("\n");
}
The program output is
4 5 9 6 7 1 8 2 4 5
9 1 4 5 6 7 8 2 4 5
You're not actually altering the array.
In the second loop, you say "if the current element is the max, set it to the max". In other words, set it to its current value. Similarly for the min.
What you want is to swap those assignments.
if(a[i]==max) a[i]=min;
if(a[i]==min) a[i]=max;
Also, your initial values for min and max are no good. min is unitialized, so its initial value is undefined. You should initialize min to a very large value, and similarly max should be initialized to a very small (i.e. large negative) value.
A better way to do this would be to keep track of the index of the largest and smallest values. These you can initialize to 0. Then you can check a[i] > a[max] and a[i] < a[min]. Then you print the values at indexes min and max, then loop through the list and print the others.
int i, temp, min=0, max=0;
for (i=1; i<10; i++) {
if (a[i] > a[max]) max = i;
if (a[i] < a[min]) min = i;
}
printf("%d %d ", a[max], a[min]);
for (i=0; i<10; i++) {
if ((i != min) && (i != max)) {
printf("%d ", a[i]);
}
}
printf("\n");
Just keep it nice and simple, like this:
#include <stdio.h>
#include <stdlib.h>
#define MAXNUM 10
int find_biggest(int A[], size_t n);
int find_smallest(int A[], size_t n);
void print_array(int A[], size_t n);
void int_swap(int *a, int *b);
int
main(void) {
int array[MAXNUM], i, smallest, biggest;
printf("Please enter 10 int values:\n");
for (i = 0; i < MAXNUM; i++) {
if (scanf("%d", &array[i]) != 1) {
printf("invalid input\n");
exit(EXIT_FAILURE);
}
}
printf("Before: ");
print_array(array, MAXNUM);
smallest = find_smallest(array, MAXNUM);
biggest = find_biggest(array, MAXNUM);
int_swap(&array[smallest], &array[biggest]);
printf("After: ");
print_array(array, MAXNUM);
return 0;
}
int
find_biggest(int A[], size_t n) {
int biggest, i, idx_loc;
biggest = A[0];
idx_loc = 0;
for (i = 1; i < n; i++) {
if (A[i] > biggest) {
biggest = A[i];
idx_loc = i;
}
}
return idx_loc;
}
int
find_smallest(int A[], size_t n) {
int smallest, i, idx_loc;
smallest = A[0];
idx_loc = 0;
for (i = 1; i < n; i++) {
if (A[i] < smallest) {
smallest = A[i];
idx_loc = i;
}
}
return idx_loc;
}
void
print_array(int A[], size_t n) {
int i;
for (i = 0; i < n; i++) {
printf("%d ", A[i]);
}
printf("\n");
}
void
int_swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}

Understanding Heaps

Every reference I look at to learn about heaps says that the sift_down approach to building heaps is the ideal way, but does this mean that it is still possible to build a heap using sift_up? If so, why is sift_down preferred? I'm trying to get a better understanding of these types of things for an algorithms course I am taking. I'd like to try to implement a build_heap function that uses sift_up, but so far I haven't had any luck, though I have managed to get it to work using sift_down.
Any ideas, suggestions, or references that anyone could share? Here's a few functions I'm struggling with at the moment:
#include <stdio.h>
void bottom_up_heapsort(int*, int);
void heapsort(int*, int);
void sift_up(int*, int);
void sift_down(int*, int);
void build_max_heap(int*, int);
void bottom_up_build_max_heap(int*, int);
void swap(int*, int*);
int heapsize;
int main() {
int A[] = { 7, 12, 1, -2, 0, 15, 4, 11, 9 };
int B[] = { 7, 12, 1, -2, 0, 15, 4, 11, 9 };
int i;
int size = 9;
printf("Unsorted array: \n");
for(i = 0; i < size; i++) {
printf(" %d ", A[i]);
}
heapsort(A, size);
printf("\n");
printf("Sorted array: \n");
for(i = 0; i < size; i++) {
printf(" %d ", A[i]);
}
printf("\n");
printf("----------------------------------\n");
printf("Unsorted array for bottom up: \n");
for(i = 0; i < size; i++) {
printf(" %d ", B[i]);
}
bottom_up_heapsort(B, size);
printf("\n");
printf("Sorted array: \n");
for(i = 0; i < size; i++) {
printf(" %d ", B[i]);
}
printf("\n");
return 0;
}
void bottom_up_heapsort(int* arr, int len) {
int i;
bottom_up_build_max_heap(arr, len);
for(i = len-1; i >= 1; i--) {
sift_up(arr, len);
heapsize--;
swap(&arr[i], &arr[0]);
}
}
void heapsort(int* arr, int len) {
int i;
build_max_heap(arr, len);
for(i = len-1; i >= 1; i--) {
swap(&arr[0], &arr[i]); // move arr[0] to its sorted place
heapsize = heapsize - 1;
sift_down(arr, 0); // repair the heap
}
}
void sift_down(int* arr, int i) {
int l = 2*i, r = 2*i+1;
int largest;
if(l < heapsize && arr[l] > arr[i]) {
largest = l;
}
else {
largest = i;
}
if(r < heapsize && arr[r] > arr[largest]) {
largest = r;
}
if(largest != i) {
swap(&arr[i], &arr[largest]);
sift_down(arr, largest);
}
}
void sift_up(int* arr, int i) {
if(i == 1) return; // at the root
if(arr[i] > arr[i/2]) {
swap(&arr[i], &arr[i/2]);
sift_up(arr, i/2);
}
}
void bottom_up_build_max_heap(int* arr, int len) {
heapsize = len;
int i;
for(i = 0; i <= len; i++) {
sift_up(arr, i);
}
}
void build_max_heap(int* arr, int len) {
heapsize = len;
int i;
for(i = len/2; i >= 0; i--) {
// invariant: arr[k], i < k <= n are roots of proper heaps
sift_down(arr, i);
}
}
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
You should be able to do
for (int i = 1; i <= n; i++) sift_up(heap, i);
which is equivalent to inserting the elements one by one. The worst-case running time is Theta(n log n), since in the worst case each new element must be sifted all the way to the root. This running time is worse than that of the sift_down heapify, namely, Theta(n). The difference is that sift_down can move the majority of elements only a couple levels down, while sift_up can move the majority of elements log n levels up.

Resources