Removing duplicate elements in array without sorting - wrong output - c

I have been trying to write a function to remove duplicate elements in an array of ints without sorting it.
For that task, I created a function named removeDuplicateElements, which gets an array and its string, and returns a new dynamically allocated array, which is a copy of the original array with removal of all duplicates elements. This function also returns by reference the size of the new array.
I also used in my code functions which build a dynamic array and print it.
Here is my code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
void printArray(int *arr, int size);
int *buildArray(int size);
int *removeDuplicateElements(int *arr, int size, int *newSize);
void main() {
int size,newSize;
int *arr;
int *newArr;
printf("please enter a number for the size of array: ");
scanf("%d", &size);
printf("\nenter %d numbers: ", size);
arr = buildArray(size);
printf("\nthe array after removing the duplicate elements is: ");
newArr = removeDuplicateElements(arr, size, &newSize);
printArray(newArr, newSize);
free(newArr);
free(arr);
}
/* this function removes all duplicate elements in a given array */
int *removeDuplicateElements(int *arr, int size, int *newSize) {
int *newArr;
int count = size, i, j;
/* finding the new size of the original array with removal its duplicate elements */
for (i = 1; i < size; i++) {
for (j = 0; j < size; j++)
if (arr[i] == arr[j] && i != j) {
count--;
break;
}
}
newArr = (int*)malloc(count * sizeof(int)); /* dynamically allocating the new array */
count = 1;
newArr[0] = arr[0];
/*adding the elements in the new array without changing the order*/
for (i = 1; i < size; i++) {
for (j = 0; j < size; j++) {
if (arr[i] == arr[j] && i != j) {
break;
}
if (j == size - 1) {
newArr[count] = arr[i];
count++;
}
}
}
*newSize = count; /* updating the size of the new array */
return newArr; /* returning the address of new array */
}
void printArray(int *arr, int size) {
int i;
for (i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int *buildArray(int size) {
int i;
int *arr = (int*)malloc(size * sizeof(int));
if (!arr) {
printf("ERROR! Not enough memory!\n");
exit(1);
}
for (i = 0; i < size; i++)
scanf("%d", &arr[i]);
return arr;
}
I get a wrong output for that code, and I dont understand why
For instance, for the following array with size=5 :1 1 3 1 3
I get the wrong output 1, whereas the expected outout is
1 3.
Any help would be appreciated.

You're firstly calculating the size of the new array incorrectly. For your example input, when you're looking at the first 3, it scans the whole array to see how many 3's there are and finds there are 2 and concludes it's a duplicate. It then does the exact same thing for the 2nd 3. So you end up with the size of the new array as 1.
Instead of scanning the whole array, you only want to scan the array for the elements preceding the one you're checking. So something like this.
for(i=1;i<size;i++)
{
for (j = 0; j < i; j++)
if (arr[i] == arr[j])
{
count--;
break;
}
}
And for the code that fills the new array has the same problem
for(i=1;i<size;i++)
{
for (j = 0; j < i; j++)
if (arr[i] == arr[j])
{
break;
}
if(j==i)
{
newArr[count++]=arr[i];
}
}

There is an alternative way of doing it, ofcourse it involves modifying the original array but this is just an alternative. Basically it involves crossing off the duplicate element by replacing it with a maximum value like 0xFFFF.
int* removeDuplicateElements(int *arr, int size, int *newSize)
{
int *newArr;
int count = size, i, j;
int index = 0;
/*finding the new size of the original array with removal its duplicate elements*/
for(i=0;i<size;i++)
{
for (j = i+1; j < size; j++)
if (arr[i] == arr[j] && arr[i] != 0xFFFF)
{
count--;
arr[j] = 0xFFFF;
}
}
printf("Size is %d \n", count);
newArr = (int*)malloc(count * sizeof(int)); /*dynamically allocating the new array*/
for(i=0;i<size;i++)
{
if(arr[i] != 0xFFFF)
newArr[index++] = arr[i];
}
*newSize = count; /*updating the size of the new array*/
return newArr; /*returning the address of new array*/
}

Related

I want to print a sorted array in C using count sort but my code is not working

I want to print a sorted array in C using count sort but my code is not working !
I watched a tutorial of the countsort algorithm and copied the code from the video but for some reason my code is not working while the code runs in the video .
I also wrote comments based on the work that the part of the code is doing in this script.
The output should be the given array and a sorted array on next line
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
void displayArray(int *arr,int size){
printf("[ ");
for(int i=0; i<size; i++){
printf("%d ",arr[i]);
}
printf("]\n");
}
int maximum(int A[], int size){
int max = INT_MIN;
for(int i=0; i<size; i++){
if(max < A[i]){
max = A[i];
}
}
return max;
}
void countSort(int* A, int size){
int i,j;
// Find the maximum element in Array
int max = maximum(A,size);
// Create the count array
int* count = (int*) malloc((max+1)*sizeof(int));
// Initialize the count array elements to zero
for(i=0; i < size+1; i++){
count[i] = 0;
}
// Increment the corrosponding index in the count array
for(i=0; i<size; i++){
count[A[i]] = count[A[i]] + 1;
}
i = 0; // Counter for count array
j = 0; // Counter for given array
while(i <= max){
if(count[i] > 0){
A[j] = i;
count[i] = count[i] - 1;
j++;
}
else{
i++;
}
}
}
int main(){
int A[] = {56,23,53,13,64,34};
int n = 6;
displayArray(A,n);
countSort(A,n);
displayArray(A,n);
return 0;
}
This loop
// Initialize the count array elements to zero
for(i=0; i < size+1; i++){
count[i] = 0;
}
does not set all elements of the dynamically allocated array to zeroes.
It seems you mean
// Initialize the count array elements to zero
for(i=0; i < max+1; i++){
count[i] = 0;
}
Or if to include the header <string.h> then you can write
memset( count, 0, ( max + 1 ) * sizeof( int ) );
Or you could initially allocate and initialize the array with zeroes using standard function calloc instead of malloc.
Pay attention to that the code will not work if the array contains negative numbers.

Deleting occurrences of an element in an array in 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");
}

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

Why doesn't the if statement get executed in the function

I am trying to do my homework but I got stuck. They want me to take one array which is already given and separate it into two arrays, one of them holds the even numbers and the other holds the odd numbers. I wrote a void function that receives 6 parameters as I will show below. The if statement: (if ((arr[j]%2) == 0)) in the function does not get executed for some reason. It just skips it. I don't really understand why and I'd appreciate any assistance.
Tried debugging, using different syntax for the pointers Arr1 and Arr2.
#include <stdio.h>
#include <malloc.h>
void separate(int* arr, int n, int* size1, int* size2, int* arr1, int* arr2);
int main()
{
int size1=0, size2=0;
int* newArr1 = NULL;
int* newArr2 = NULL;
int arr[] = { 6,57,14,21,11,3,22,42,9,15 };
printf("The array before change:\n");
for (int i = 0; i <10; i++)
{
printf(" %d", arr[i]);
}
printf("\n");
separate(arr, 10, &size1, &size2, newArr1, newArr2);
printf("The even array is:\n");
for (int i = 0; i <size1; i++)
{
printf(" %d", newArr1[i]);
}
printf("\n");
printf("The odd array is:\n");
for (int i = 0; i <size2; i++)
{
printf(" %d", newArr2[i]);
}
printf("\n");
system("pause");
return 0;
}
void separate(int* arr, int n, int* size1, int* size2, int* arr1, int* arr2)
{
int i, j;
for (i = 0; i < n; i++)
{
if (arr[i] % 2 == 0)
(*size1)++;
else
(*size2)++;
}
printf("\n");
printf("size1: %d size2: %d", (*size1),(*size2));
arr1 = (int*)calloc((*size1), sizeof(int));
arr2 = (int*)calloc((*size2), sizeof(int));
for (j = 0; j < n; j++)
{
if ((arr[j]%2) == 0)
arr1[j] == arr[j];
}
for (j = 0; j < n; j++)
{
if (arr[j] % 2 != 0)
arr2[j]== arr[j];
}
return;
}
Does not compile
Turn on warnings! You're trying to use a '==' for assignment - should be '='.
gcc -std=c99 -Wall omg.c -o omg
omg.c: In function 'main':
omg.c:32:5: warning: implicit declaration of function 'system' [-Wimplicit-function-declaration]
system("pause");
^
omg.c: In function 'separate':
omg.c:55:9: warning: statement with no effect [-Wunused-value]
arr1[j] == arr[j];
^
omg.c:61:13: warning: statement with no effect [-Wunused-value]
arr2[j]== arr[j];
^
This is wrong
for (j = 0; j < n; j++)
{
if ((arr[j]%2) == 0)
arr1[j] == arr[j];
}
Imagine j being the last one (n - 1). You will try to set arr1[n - 1] to whatever, but size of arr1 is size1 not n.
As others pointed out you are using == to try to assign values.
Your array is going out of bounds because you allocated only enough memory in your other arrays to hold the amount of even/odd numbers in the array that is being sorted. I left comments for you. Idk what compiler or ide your using but I got this working on Visual Studio, with some other changes to the code. I am also a student!
void separate(int* arr, int n, int* size1, int* size2, int* arr1, int* arr2)
{
int i, j;
for (i = 0; i < n; i++)
{
if (arr[i] % 2 == 0)
(*size1)++;
else
(*size2)++;
}
printf("\n");
printf("size1: %d size2: %d", (*size1), (*size2));
// Your assigning only enough space to hold the amount of even/odd numbers
arr1 = (int*)calloc((*size1), sizeof(int));
arr2 = (int*)calloc((*size2), sizeof(int));
// If the index of the array is larger than what you allocated, crash..
for (j = 0; j < n; j++)
{
if ((arr[j] % 2) == 0)
arr1[j] == arr[j];
}
for (j = 0; j < n; j++)
{
if (arr[j] % 2 != 0)
arr2[j] == arr[j]; // Use = to assign, not ==
}
return;
}

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.

Resources