Shifting array to replace removed element - c++

I am supposed to get the output 8, 6. But I get 8,9 when this code is run. Why am I getting the out put 8,6 and how can I fix the code to make the output become 8,9.
int inputarray[]={9,8,9,9,9,9,6};
int length = 7;
int value = 9;
void arrayShift(int arr[], int length, int value)
{
for(int i = 0; i<length; i++)
{
if(arr[i] == value)
{
for (int k = i; k<length ; k++)
{
arr[k] = arr[k+1];
}
arr[length-1] = 0;
}
}
}

When shifting array, you may replace first element (containing number equal to value) with the same value from other element. In that case, you need to restart iteration on this element again, e.g.:
void arrayShift(int arr[], int length, int value)
{
for(int i = 0; i<length; i++)
{
if(arr[i] == value)
{
for (int k = i; k<length-1 ; k++)
{
arr[k] = arr[k+1];
}
arr[length-1] = 0;
i--; // <-- this
}
}
}

Your algorithm for shifting is wrong: you fail to adjust i on removal. In addition, it is rather inefficient: you can do this in a single loop with two indexes - r for reading and w for writing. When you see the value you want to keep, adjust both the reading and the writing index. Otherwise, increment only the reading index.
Once the reading index reaches the count, the writing index indicates how many items you have left. You need to return it to the caller somehow, otherwise he wouldn't know where the actual data ends. You can return the new length as the return value of your function, or take length as a pointer, and adjust it in place.
int arrayShift(int arr[], int length, int value) {
int r = 0, w = 0;
for (; r != length ; r++) {
if (arr[r] != value) {
arr[w++] = arr[r];
}
}
return w;
}
Here is how you call it:
int inputarray[]={9,8,9,9,9,9,6};
int length = 7;
int value = 9;
int newLen = arrayShift(inputarray, length, value);
for (int i = 0 ; i != newLen ; i++) {
printf("%d ", inputarray[i]);
}
printf("\n");
Demo.

Related

Getting different output on each execution

I tried to implement number of inversions in an array, using merge sort.
Every time I execute this code, I get different value of the number of inversions. I am not able to figure out the reason for this. Please have a look at the code and tell me the mistake.
#include<stdio.h>
#include<iostream>
using namespace std;
int count =0;
void merge(int A[],int start,int mid,int end)
{
int size1 = mid-start+1;
int size2 = end-(mid+1)+1;
int P[size1];
int Q[size2];
for(int i=0;i<size1;i++)
P[i]=A[start+i];
for(int j=0;j<size2;j++)
Q[j]=A[mid+j+1];
int k = 0;
int l = 0;
int i =0;
while(k<mid && l<end)
{
if(P[k]>Q[l])
{
A[i] = Q[l];
l++; i++;
count++;
}
else
{
A[i] = P[k];
k++; i++;
}
}
}
void inversions(int A[],int start,int end)
{
if(start!=end)
{
int mid = (start+end)/2;
inversions(A,start,mid);
inversions(A,mid+1,end);
merge(A,start,mid,end);
}
}
int main()
{
int arr[] = {4,3,1,2,7,5,8};
int n = (sizeof(arr) / sizeof(int));
inversions(arr,0,n-1);
cout<<"The number of inversions is:: "<<count<<endl;
return 0;
}
int k = 0;
int l = 0;
int i =0;
while(k<mid && l<end)
{
if(P[k]>Q[l])
{
A[i] = Q[l];
l++; i++;
count++;
}
else
{
A[i] = P[k];
k++; i++;
}
}
Few mistakes here, i starts from start and not 0. k must loop from 0 till size1 and not till mid. Similarly, l must loop from 0 till size2 and not till end. You are incrementing count by 1 when P[k] > Q[l] but this is incorrect. Notice that all the elements in array P following the element P[k] are greater than Q[l]. Hence they also will form an inverted pair. So you should increment count by size1-k.
Also, the merge procedure should not only count the inversions but also merge the two sorted sequences P and Q into A. The first while loop while(k<size1 && l<size2) will break when either k equals size1 or when l equals size2. Therefore you must make sure to copy the rest of the other sequence as it is back into A.
I have made the appropriate changes in merge and pasted it below.
void merge(int A[],int start,int mid,int end)
{
int size1 = mid-start+1;
int size2 = end-(mid+1)+1;
int P[size1];
int Q[size2];
for(int i=0;i<size1;i++)
P[i]=A[start+i];
for(int j=0;j<size2;j++)
Q[j]=A[mid+j+1];
int k = 0;
int l = 0;
int i = start;
while(k<size1 && l<size2)
{
if(P[k]>Q[l])
{
A[i] = Q[l];
l++; i++;
count += size1-k;
}
else
{
A[i] = P[k];
k++; i++;
}
}
while (k < size1)
{
A[i] = P[k];
++i, ++k;
}
while (l < size2)
{
A[i] = Q[l];
++i, ++l;
}
}
int P[size1];
int Q[size2];
VLA (Variable length arrays) are not supported by C++. size1 and size2 are unknown during compile time. So, each time they get a different value and hence the difference in output.
Use std::vector instead
std::vector<int> P(size1, 0); //initialize with size1 size
std::vector<int> Q(size2, 0); //initialize with size2 size

Sorting an array of values by shifting to the right

I have to make a method that sorts an array of values going from lowest value to the highest. The way these functions are supposed to work is that it grabs each value, tries to put them in rising order going from left to right by shifting every bigger value to the right.
I have made the following functions:
int findIndex(double *arr, double num, int length)
{
for (int i = 0; i < length; i++)
{
if (arr[i] > num)
return i;
}
return length - 1;
}
void placeOnIndex(double *arr, double num,int index, int length)
{
if (length > 1 && arr[index] != num)
{
for (int i = length - 1; i > 0; i--)
{
arr[i] = arr[i - 1];
}
arr[index] = num;
}
}
void insertSort(double* arr, int length)
{
for (int ix = 0; ix < length; ix++)
{
double num = arr[ix]; //Current value to put as far to the left as possible
int index = findIndex(arr, num, ix+1); //Locates index to put it
placeOnIndex(arr, num, index, ix+1); //Uses the index to put in the right place
}
}
void main()
{
double arr[4] = {1,8,4,5};
insertSort((arr), 4);
}
My problem is that the output with this array becomes:
1,1,5,8
Apparently it sometimes overrides the second element in my array. Sometimes it works and sometimes it doesn't. If the array is longer even more values are overridden.
I'm sorry if it looks confusing, english isn't my native tongue.
This line
for (int i = length - 1; i > 0; i--)
causes all the elements to move right, not just the ones that should move.
You need
for (int i = length - 1; i > index; i--)

The most occuring number in structure(array)

I cant find out whats wrong with this part of my program, i want to find out most occuring number in my structure(array), but it finds only the last number :/
void Daugiausiai(int n)
{
int max = 0;
int sk;
for(int i = 0; i < n; i++){
int kiek = 0;
for(int j=0; j < n; j++){
if(A[i].datamet == A[j].datamet){
kiek++;
if(kiek > max){
max = kiek;
sk = A[i].datamet;
}
}
}
}
}
ps. its only a part of my code
You haven't shown us enough of your code, but it is likely that you are not looking at the real result of your function. The result, sk is local to the function and you don't return it. If you have global variable that is also named sk, it will not be touched by Daugiausiai.
In the same way, you pass the number of elements in your struct array, but work on a global struct. It is good practice to "encapsulate" functions so that they receive the data they work on as arguments and return a result. Your function should therefore pass both array length and array and return the result.
(Such an encapsulation doesn't work in all cases, but here, it has the benefit that you can use the same function for many different arrays of the same structure tape.)
It is also enough to test whether the current number of elements is more than the maximum so far after your counting loop.
Putting all this together:
struct Data {
int datamet;
};
int Daugiausiai(const struct Data A[], int n)
{
int max = 0;
int sk;
for (int i = 0; i < n; i++){
int kiek = 0;
// Count occurrences
for(int j = 0; j < n; j++){
if(A[i].datamet == A[j].datamet) kiek++;
}
// Check for maximum
if (kiek > max) {
max = kiek;
sk = A[i].datamet;
}
}
return sk;
}
And you call it like this:
struct Data A[6] = {{1}, {2}, {1}, {4}, {1}, {2}};
int n = Daugiausiai(A, 6);
printf("%d\n", n); // 1
It would be nice if you had english variable names, so I could read them a bit better ^^. What should your paramter n do? Is that the array-length? And what should yout funtion do? It has no return value or something.
int getMostOccuring(int array[], int length)
{
int current_number;
int current_count = 0;
int most_occuring_number;
int most_occuring_count = 0;
for (int i = 0; i < length; i++)
{
current_number = array[i];
current_count = 0;
for (int j = i; j < length; j++)
{
int test_number = array[j];
if (test_number == current_number)
{
current_count ++;
if (current_count > most_occuring_count)
{
most_occuring_number = current_number;
most_occuring_count = current_count;
}
}
}
}
return most_occuring_number;
}
this should work and return the most occuring number in the given array (it has a bad runtime, but is very simple and good to understand).

Inserting value into sorted array without duplicates: C++

For this program I have three data files. The first has a list of numbers, the second is a list of numbers with an add (A) or delete (D) command. I have to put the numbers from the first file into the third file, then update the final file based on the commands and numbers in the second file. The third file cant have duplicates and must be sorted while values are being inserted. Here are the functions I have, I'm having difficulty getting the items stored into the array without duplicates. The array must be statically sized, I did a #define of max size 2000 which is more than enough to handle the numbers I need. Thanks so much! If I should upload the main let me know, but I'm fairly certain the problem lies in one of these functions.
int search(int value, int list[], int n) // returns index, n is logical size of array
{
int index = -1;
for(int i = 0; i < n; i++)
{
if(value == list[i])
{
index = i;
return index;
}
}
return index;
}
void storeValue(int value, int list[], int& n)
{
int i = n;
for(; i > 0 && list[i - 1] < value; i--)
{
list[i] = list[i - 1];
}
list[i] = value;
n++;
}
void deleteValue(int loc, int list[], int n)
{
if(loc >= 0 && loc < n)
{
for(int i = loc; i < n - 1; i++)
list[i] = list[i +1];
n--;
}
}
UPDATE: Now duplicates are being stored, but only for some numbers.
For example: my 3rd file is: 1,2,8,8,9,101,101,104,etc.
The output should be: 1,2,8,9,101,104,etc
value: value to be inserted
list[]: array being modified (must be static)
n: logical size of array
I can't figure out why some numbers are duplicated and others aren't
In my main, I run the search function and if a -1 is returned (the value isn't already found) then I run the storeValue function.
Here are my updated functions:
int search(int value, int list[], int n) // returns index
{
int index = -1;
for(int i = 0; i < n; i++)
{
if(value == list[i])
{
index = i;
return index;
}
}
return index;
}
void storeValue(int value, int list[], int& n)
{
int i = n;
for(; i > 0 && list[i - 1] > value; i--)
{
list[i] = list[i - 1];
}
list[i] = value;
n++;
}
void deleteValue(int loc, int list[], int& n)
{
if(loc >= 0 && loc < n)
{
for(int i = loc; i < n; i++)
{
if (i == loc)
{
list[i] = list[i + 1];
i++;
}
}
n--;
}
}
In your deleteValue function, you are deleting the value, but will end up with a duplicate because you are just reassigning the current index to the next value. For example, if you have the array:
char array[3] = [1, 2, 3];
and you wanted to delete the second integer, your function currently would output this:
[1, 3, 3]
What you want to do is make a new array and loop through your entire list, making sure to leave out the last element like so:
char* deleteValue(int loc, int list[], int n)
{
char* newArray[n - 1];
if (loc >= 0 && loc < n)
{
for (int i = 0; i < n - 1; i++)
{
if (i == loc) // You have arrived at the element that needs to be deleted
{
newArray[i] = list[i + 1];
i++; // So we skip over the deleted element
}
else
newArray[i] = list[i];
}
}
return newArray;
}
And this should take care of the case where the last value is duplicated.

How to use selection sort algorithm correctly to sort a list?

I cannot get this to work, seems like whatever I do it never sorts correctly.
I am trying to sort in a descending order based on number of points.
Bryan_Bickell 2 5 +2
Brandon_Bolig 0 3 0
Dave_Bolland 4 2 -1
Sheldon_Brookbank 0 4 -1
Daniel_Carcillo 0 1 +3
The middle column is the amount of points.
I am using 4 arrays to store all of those values, how would I correctly utilize the array selection sort to get it to order in the right way?
I had tried all the answers below but none of them seemed to work, this is what i have so far
void sortArrays( string playerNames[], int goals[], int assists[], int rating[], int numPlayers )
{
int temp, imin;
int points[numPlayers];
for(int j = 0; j < numPlayers; j++)
{
points[j] = goals[j] + assists[j];
}
imin = points[0];
for(int i = 0; i < numPlayers; i++)
{
if (points[i] < imin)
{
imin = points[i];
}
}
for(int j = 1; j < numPlayers; j++)
{
if (points[j] > imin)
{
temp = points[j];
points[j] = points[j-1];
points[j-1] = temp;
}
}
}
it should go like this...
void selsort(int *a,int size)
{
int i,j,imin,temp;
//cnt++;
for(j=0;j<size;j++)
{
//cnt+=2;
imin=j;
for(i=j+1;i<size;i++)
{
//cnt+=2;
if(a[i]<a[imin])
{
//cnt++;
imin=i;
}
}
if(imin!=j)
{
//cnt+=3;
temp=a[j];
a[j]=a[imin];
a[imin]=temp;
}
}
}
You don't need 4 arrays to store those records if only the middle column is used for sorting, i.e, keys used for sorting the records. From my understanding, you are trying to sort those records of people based on the number of points with selection sort. Code should look like the following: assuming records is your array of records
void selectionSort(RECORD records[], int n) {
int i, j, minIndex, tmp;
for (i = 0; i < n - 1; i++) {
maxIndex = i;
for (j = i + 1; j < n; j++) //find the current max
{
if (records[j].point > records[minIndex].point)
{
//assume point is the number of point, middle column
minIndex = j;
}
}
//put current max point record at correct position
if (minIndex != i) {
tmp = records[i];
records[i] = records[minIndex];
records[minIndex] = tmp;
}
}
}
It will sort all your records in "descending order" as you want
how about store the data into a std::vector then sort it
int compare(int a, int b){
return (a>b);
}
void sort(std::vector<int> &data){
std::sort(data.begin(), data.end(), compare);
}
try to use vector as much possible, they have been heavy optimized for performance and better memory usage