I made a merge sort function:
void mergeSort(int emotionCount[], int low, int high){
int i=0,k=0;
//I did this to see the value inside the array, and I always got a garbage value
//when i=0, and the first correct value when i=1. I made a for loop here to
//see the values in the array in debugging mode in netbean.
for (i=0;i<=high;i++){
}
if (low == high){
emotionCount[low]=emotionCount[low];
}else{
int mid = (low+high)/2;
mergeSort(emotionCount,low,mid);
mergeSort(emotionCount,mid+1,high);
merge(emotionCount, low,mid, high); }
}
void merge(int emotionCount[], int low,int mid, int high)
{
int temp[high-low+1];
int i=low,k=mid+1, j=high, n=0;
int comparing=emotionCount[k];
while (i<=mid || k<=high){
while (emotionCount[i]<comparing)
{
temp[n]=emotionCount[i];
i++;
n++;
}
comparing=emotionCount[i];
temp[n]=emotionCount[k];
k++;
i++;
n++;
while (emotionCount[k]<comparing){
temp[n]=emotionCount[k];
k++;
n++;
}
comparing=emotionCount[k];
temp[n]=emotionCount[i];
k++;
i++;
n++;
}
while (i<=mid)
{
temp[n]=emotionCount[i];
i++;
n++;
}
while (k<=high)
{
temp[n]=emotionCount[k];
k++;
n++;
}
while (low<=high)
{
emotionCount[low]=temp[i];
low++;
}
}
And in main, i pass an array:
int array[10] = {0,5,8,2,4,6,8,2,20,25};
//number 9 because the highest position is 9. After this, array[10] is supposed to be sorted.
mergeSort(array ,0, 9);
Well, the method was kinda long, but I want to implement it myself. Basically, I pass an array to the mergeSort function, and if it is not at its minimum size (which is 1), it will continue to pass that array. The thing which bugging me is, when I pass an array to it, the first value is always a garbage value (like an address value or something). Only after i=1, it will give the first value of the array. I don't get it. Also, everytime exiting a lower mergeSort function to continue on the higer ones, all the sorted values in the array become 0.
Edit: The k variable is just used to hold the array value, to see the array value when I'm in debugging mode. I removed the k variable in the mergeSort function to clear up the confusion.
Yet to read through your function, but at first glance the problem that stands out is the way you are calling the function.
It should be :
mergeSort(array, 0, 9);
If you use array[10], it means you're trying to pass in the 11th element of the array which is unfortunately out of bounds!
It looks like you're passing a value from inside the array instead of the array itself: shouldn't
mergeSort(array[10] ,0, 9);
be something like
mergeSort(array, 0, 0);
for (i=0;i<=high;i++){
int k=*(emotionCount+i);
}
if (low == high){
emotionCount[low]=emotionCount[low];
int k=emotionCount[low];
}else{
int mid = (low+high)/2;
mergeSort(emotionCount,low,mid);
int i=0;
for (i=low;i<=mid;i++){
int k=emotionCount[i];
}
mergeSort(emotionCount,mid+1,high);
for (i=mid+1;i<=high;i++){
int k=emotionCount[i];
}
merge(emotionCount, low,mid, high);
for (i=low;i<=high;i++){
int k=emotionCount[i];
}
}
You redeclare int k in all those blocks. I assume you want to assign a value to k instead so remove the leading "int". Just as in Java which you claim to be familiar with.
What do you want to do anyway? Even if you would use your globally declared k assigning all array elements in a loop doesn't make sense at all. Basically you would end up with k being equal to emotionCount[high].
Do you know that you can dereference array elements using the [] syntax?
k = emotionCount[i]
Is easier to read.
You use Netbeans which has a nice GDB frontend. I suggest that you set a few breakpoints, step through your code and try to understand what you implemented there.
I solved the problem. Corrected code:
void mergeSort(int emotionCount[], int low, int high){
int i=0,k=0;
if (low == high){
emotionCount[low]=emotionCount[low];
k=emotionCount[low];
}else{
int mid = (low+high)/2;
mergeSort(emotionCount,low,mid);
/*
int i=0;
printf("Lower half:");
for (i=low;i<=mid;i++){
k=emotionCount[i];
printf("%d ",k);
}
printf("\n");*/
mergeSort(emotionCount,mid+1,high);
/*
printf("Upper half:");
for (i=mid+1;i<=high;i++){
k=emotionCount[i];
printf("%d ",k);
}
printf("\n");*/
merge(emotionCount, low,mid, high);
//this is how I view the sorting process, along with other 2 above loops
/* printf("Merged:");
for (i=low;i<=high;i++){
k=emotionCount[i];
printf("%d ",k);
}
printf("\n\n");*/
}
}
void merge(int emotionCount[], int low,int mid, int high)
{
int temp[high-low+1],index;
for (index=0;index<high-low+1;index++)
{
temp[index]=0;
}
int i=low,k=mid+1, j=high, n=0;
int comparing=emotionCount[k],temp1;
while (i<=mid && k<=high){
while (emotionCount[i]<comparing && i<=mid)
{
temp[n]=emotionCount[i];
i++;
n++;
}
if (i<=mid){
comparing=emotionCount[i];
if (k<=high)
temp[n]=emotionCount[k];
else
temp[n]=comparing;
k++;
n++;
}
while (emotionCount[k]<comparing && k<=high){
temp[n]=emotionCount[k];
k++;
n++;
}
if (k<=high){
comparing=emotionCount[k];
if (i<=mid)
temp[n]=emotionCount[i];
else
temp[n]=comparing;
i++;
n++;
}
}
while (i<=mid)
{
temp[n]=emotionCount[i];
i++;
n++;
}
while (k<=high)
{
temp[n]=emotionCount[k];
k++;
n++;
}
i=0;
while (low<=high)
{
emotionCount[low]=temp[i];
low++;
i++;
}
}
The initial high value must be exactly array size - 1.
Related
I am doing practice questions from geeksforgeeks. And I'm unable to solve the question and get the required output.
https://practice.geeksforgeeks.org/problems/max-sum-path-in-two-arrays/1/?category[]=Arrays&company[]=Amazon&difficulty[]=0&page=1&sortBy=submissions&query=category[]Arrayscompany[]Amazondifficulty[]0page1sortBysubmissions
//I am finding the max path using the merge sort algo, where T(n)=O(m+n)
int MaxPath(int a[],int b[],int n,int m){
int i, j, result=0, sum1=0, sum2=0; // sum1 and sum2 store the sums of 1st and 2nd arrays respectively
while(i<n && j<m){
if(a[i]<b[j]){
sum1+=a[i++];
}
else if(a[i]>b[j]){
sum2+=b[j++];
}
else{
result+=Max(sum1,sum2);
sum1=0;
sum2=0;
int temp=i;
while(i<n && a[i]==b[j]){
sum1+=a[i++];
}
while(j<m && a[temp]==b[j]){
sum2+=b[j++];
}
result+=Max(sum1,sum2);
sum1=0;
sum2=0;
}
}
while(i<n){
sum1+=a[i++];
}
while(j<m){
sum2+=b[j++];
}
result+=Max(sum1,sum2);
return result;
}
Undefined behavior at beginning of code. This statement:
while(i<n && j<m){
Is called before the value of i, or j is set:
int i, j, result=0, sum1=0, sum2=0;
Note that the other items created have been set, but not i and j.
It is therefore undefined from this point on how this while loop will perform. Initialize all variables before they are used.
I can not properly print the steps given by the quicksort algorithm. This function works when N=1, which means that the values in the matrix only repeat once, but for N>1 it does not print it properly.
This is for a program I am writing to represent the different sorting algorithms steps with the console.
void quicksort(int *target, int left, int right) {
char charac[MAX*N][MAX]; // this is the array I am going to print on screen
if(left >= right)
return;
int i = left, j = right;
int tmp, pivot = target[i];
for(;;) {
while(target[i] < pivot)
i++;
while(pivot < target[j])
j--;
if(i >= j)
break;
tmp = target[i];
target[i] = target[j];
target[j] = tmp;
i++; j--; //normal quicksort until here
for(int k=0;k<MAX*N;k++){ /*Here begin two loops that put the cursor on a certain point on the screen and then gives values to char[][]*/
GotoXY(k+30,5);
for(int l=0;l<MAX;l++){
If(l<target[k]) // if the value of the given vector is lower than l writes a space
charac[k][l]=32;
else
charac [k][l]=219; // else a block
printf("%c ",charac[k][l]); // print the block or space
GotoXY(k+35,5+l); // go to the next point of the column
}
printf("\n");
}
system("cls"); // clear the screen for the next graph
}
quicksort(target, left, i-1);
quicksort(target, j+1, right);
}
I expect to sort the values properly even if they are repeated but the result are not even close to that.
Here it is for N=1 at the beginning:
At the end:
With N=2 it is generated properly:
But this is the result:
It is not even close to something fine.
Thanks for your time.
I have a this program to receive a struct, store it and then sort it. I have tried to use Shell Sort, but then I went for the Quick Sort Algorithm. However, when I try to print the array after sorting, it still returns it unsorted. Bear in mind im trying to sort it by 'num_aluno'.
CODE
typedef struct ALUNO
{
char primeiro_nome[15];
char segundo_nome[15];
int num_aluno;
float nota;
}ALUNO;
void swap(ALUNO* a, ALUNO* b)
{
ALUNO t=*a;
*a=*b;
*b=t;
}
int partition(ALUNO *studentList, int low, int high)
{
int pivot= studentList[high].num_aluno;
int i=(low-1);
int j;
for(j=low;j<=high-1;j++)
{
if(studentList[j].num_aluno<=pivot);
{
i++;
swap(&studentList[i], &studentList[j]);
}
}
swap(&studentList[i+1], &studentList[high]);
return(i+1);
}
void quickSort(ALUNO *studentList, int low, int high)
{
if(low<high)
{
int pi=partition(studentList, low, high);
quickSort(studentList, low, pi-1);
quickSort(studentList, pi+1, high);
}
}
int main()
{
ALUNO *studentList=NULL;
int currentPos, studentListSize=1;
//float grade_sum=0;
studentList=(ALUNO*)calloc(studentList, studentListSize*sizeof(ALUNO));
printf("Insira o numero de alunos \n");
scanf("%d", &studentListSize);
studentList=(ALUNO*)realloc(studentList, studentListSize*sizeof(ALUNO));
for(currentPos=0;currentPos<studentListSize;currentPos++)
{
newStudent(studentList, currentPos);
}
quickSort(studentList, 0, studentListSize);
for(currentPos=0;currentPos<studentListSize;currentPos++)
{
printStudent(studentList,currentPos);
}
free(studentList);
return 0;
}
Any help would be appreciated
The reason it doesn't sort the list is, i and j are always the same value in the partition function.
You should start j from high -1, not from low.
Also, you are not considering the values of studentList[i]. You must guarantee that it is larger than pivot, otherwise there may be a value which is smaller than the pivot, yet at the left part of the array.
Here, corrected it.
int partition(ALUNO*studentList, int low, int high)
{
int pivot = studentList[high].num_aluno;
int i=low ;
int j;
for(j=high-1;j>=i;)
{
while(studentList[i].num_aluno < pivot)
i++;
while(studentList[j].num_aluno > pivot)
j--;
if(i<=j){
swap(&studentList[i], &studentList[j]);
i++;
j--;
}
}
swap(&studentList[i], &studentList[high]);
return(i+1);
}
An additional advice in case you have not heard of it, do not choose the first or last values as pivots. Instead, use the median of three strategy.
Median of three strategy: Pick the first, middle and last elements in the unsorted array. Change their locations according to their values in a sorted manner. Then take the middle value and use it as a pivot. This way you are avoiding the worst time complexity(O(n^2)) of QuickSort.
Here I made a quicksort implementation that uses (at least tries to) a little trick that is possible because I know the input is a list of numbers in the set {1,2,...,1023}. In particular I am not using a pivot that is necessarily in the list itself. Here is the main part of the function
int partition2(int length, int arr[], int mask) {
int left = 0;
int right = length;
while (left < right) {
while ((left < right) && (!((arr[left])&mask)) ) {
left++;
}
while ((left < right) && ((arr[right-1])&mask)) {
right--;
}
if (left < right) {
right--;
swap(left, right, arr);
left++;
}
}
left--;
return left;
}
void qSort2(int length, int arr[], int mask) {
int boundary;
if (length <= 1) {
return; /* empty or singleton array: nothing to sort */
}
boundary = partition2(length, arr, mask);
qSort2(boundary, arr,mask/2);
qSort2(length - boundary - 1, &arr[boundary + 1], mask/2);
}
main(){
int length = 200;
int *arr;
arr = generateNumbers(length);
qSort2(length, arr, 512);
int i;d
for(i=0;i<length;i++){
printf("%d ", arr[i]);
}
}
Sorry for the lengthy code. The function generateNumbers just makes a vector of size length with numbers from the given range and swap simply swaps two elements from the array. Now I am trying to exploit the fact that all numbers are smaller that 1024. So roughly speaking half of them will contain a 1 in binary representation in the position corresponding to 2^9=512. So we can use that to split the list in two lists. Then we check for both list what the digit corresponding to 2^8 is and split the list again. I am using the variable mask for this and the operator n&mask is zero if the is smaller then mask and non zero if it is larger that mask. For some reason though, it does not seem to work. Does anyone have any idea why? The output list is almost sorted but there are just some mistakes at certain places. If anyone could help me out that would be great. Thanks!
Here is the generateNumbers function:
void *makeDynamicIntArray(int length) {
void *ptr = malloc(length*sizeof(int));
if (ptr == NULL) {
printf("\nMalloc failed: out of memory?\n");
exit(-1);
}
return ptr;
}
int *generateNumbers(int length) {
int i, *arr = makeDynamicIntArray(length);
for (i=0; i<length; i++) {
arr[i] = rand() % 1024;
}
return arr;
}
Memory allocation (rather, freeing problems) in a Merge Sort implementation in C. Here's a link to the code: http://ideone.com/UTjil7
The code is too long to be pasted here, anyway here's the main memory problem giving part:
int *MergeSort(int *A, int x, int y) //declaration
{
if(x==y) //base case, return the 1-element array itself
{
return A;
}
else
{
int size=1+y-x; //total no. of elements
int half=(x+y)/2; //halving the array
int halfsize=(size/2);
int *A1=(int *)malloc(halfsize*sizeof(int));
int *A2=(int *)malloc((size-halfsize)*sizeof(int));
A1=MergeSort(A, x, half); //calling MergeSort on 1st half of array
A2=MergeSort(A, half+1, y); //calling MergeSort on 2nd half of array
int *C; //pointer to 3rd array
C=(int *)malloc(size*sizeof(int));
int j=0; //indicator for first half
int k=0; //indicator for 2nd half
int i=0; //indicator for 3rd array
while((j<=half)&&(k<=half)) //till all the elements from either half are not exhausted
{
if(A1[j]<=A2[k]) //if element of first half is smaller, put that in C
{
C[i]=A1[j];
j++;
}
else //otherwise put element of second half in C
{
C[i]=A2[k];
k++;
}
i++; //increment indicator for C
}
int flag;
if(j==(half+1))
{
flag=1;
}
else if(k==(half+1))
{
flag=2;
}
if(flag==1) //if first half is finished
{
while(i<size) //transfer all elements of second half in C
{
C[i]=A2[k];
i++;
k++;
}
}
else if(flag==2) //if second half is finished
{
while(i<size) //transfer all elements of 1st half in C
{
C[i]=A1[j];
i++;
j++;
}
}
for(int i=x;i<=y;i++) //copyback
{
A[x]=C[i-x];
}
free(A1); //Line 105
free(A2); //Line 106
free(C);
return A;
}
}
It gives me Aborted(core dumped) after taking input and trying to run.
I ran the code using Valgrind. It says "invalid free" at Line 105 and 106.
Help would be much appreciated!
int *A1=(int *)malloc(halfsize*sizeof(int));
int *A2=(int *)malloc((size-halfsize)*sizeof(int));
A1=MergeSort(A, x, half); //calling MergeSort on 1st half of array
A2=MergeSort(A, half+1, y); //calling MergeSort on 2nd half of array
you are allocating A1, A2, and then overwriting the pointers (if I follow the recursion correctly with A)