C++ quicksort with pointers - c++

Can someone point out the mistake in my code? Sorry for misleading names of function arguments - rptr should be rvalue or somethings etc, I was constantly changing something.
Most of it should be done using pointers.
I think the mistake might be in partArr, returning invalid variable, but i dont really know.
#include <iostream>
const int ArSize = 10;
void swap(int *lptr, int *rptr) {
int tempV = *lptr;
*lptr = *rptr;
*rptr = tempV;
}
int partArr(int *arr, int lptr, int rptr) {
int pivot = (lptr + rptr) / 2;
int * leftP = &lptr;
int * rightP = &rptr;
while (true) {
while (arr[*rightP] >= pivot) --(*rightP);
while (arr[*leftP] <= pivot) ++(*leftP);
if(*rightP > *leftP) {
swap(leftP,rightP);
--(*rightP);
++(*leftP);
}
else {
return rptr;
}
}
}
void quickSort(int *arr, int ptrL, int ptrR) {
if (ptrR > ptrL) {
int arr_piv = partArr(arr, ptrL, ptrR);
quickSort(arr, ptrL, arr_piv - 1);
quickSort(arr,arr_piv+1,ptrR);
}
}
int main() {
int tab[ArSize] = {10, 40, 30, 4, 3, 312, 3, 4, 1};
int ptrL = tab[0];
int ptrR = tab[ArSize - 1];
quickSort(tab, ptrL, ptrR);
for (int x : tab)
std::cout << x << " ";
return 0;
}

Here
int * leftP = &lptr;
int * rightP = &rptr;
you take the addresses of the function paramters. When you call
swap(leftP,rightP);
then you swap the values of lptr and rptr. When you write
--(*rightP)
you decrement the value of rptr. You never actually modify an element of the array.
I don't have a CS degree, hence when I want to sort an array I use std::sort:
#include <algorithm>
#include <iostream>
#include <iterator>
int main() {
int tab[] = {10, 40, 30, 4, 3, 312, 3, 4, 1};
std::sort( std::begin(tab), std::end(tab));
for (int& x : tab)
std::cout << x << " ";
return 0;
}
If you need to implement it yourself as an exercise you should to learn how to use a debugger, otherwise you will always run into problems like this. Becoming better in coding is not so much about not making mistakes, but more about knowing how to detect and fix them and a debugger is made for exactly that.

A quicksort using pointers does not need to pass the array name as a parameter. Example code:
void QuickSort(int *lo, int *hi)
{
int *i, *j;
int p, t;
if(lo >= hi)
return;
p = *(lo + (hi-lo)/2);
i = lo - 1;
j = hi + 1;
while (1){
while (*(++i) < p);
while (*(--j) > p);
if (i >= j)
break;
t = *i;
*i = *j;
*j = t;
}
QuickSort(lo, j);
QuickSort(j+1, hi);
}
The call to quick sort would be:
QuickSort(array, array+(sizeof(array)/sizeof(array[0]))-1);

Related

Find the missing numbers in the given array

Implement a function which takes an array of numbers from 1 to 10 and returns the numbers from 1 to 10 which are missing. examples input: [5,2,6] output: [1,3,4,7,8,9,10]
C++ program for the above approach:
#include <bits/stdc++.h>
using namespace std;
// Function to find the missing elements
void printMissingElements(int arr[], int N)
{
// Initialize diff
int diff = arr[0] - 0;
for (int i = 0; i < N; i++) {
// Check if diff and arr[i]-i
// both are equal or not
if (arr[i] - i != diff) {
// Loop for consecutive
// missing elements
while (diff < arr[i] - i) {
cout << i + diff << " ";
diff++;
}
}
}
}
Driver Code
int main()
{
// Given array arr[]
int arr[] = { 5,2,6 };
int N = sizeof(arr) / sizeof(int);
// Function Call
printMissingElements(arr, N);
return 0;
}
How to solve this question for the given input?
First of all "plzz" is not an English world. Second, the question is already there, no need to keep writing in comments "if anyone knows try to help me".
Then learn standard headers: Why should I not #include <bits/stdc++.h>?
Then learn Why is "using namespace std;" considered bad practice?
Then read the text of the problem: "Implement a function which takes an array of numbers from 1 to 10 and returns the numbers from 1 to 10 which are missing. examples input: [5,2,6] output: [1,3,4,7,8,9,10]"
You need to "return the numbers from 1 to 10 which are missing."
I suggest that you really use C++ and get std::vector into your toolbox. Then you can leverage algorithms and std::find is ready for you.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
std::vector<int> missingElements(const std::vector<int> v)
{
std::vector<int> missing;
for (int i = 1; i <= 10; ++i) {
if (find(v.begin(), v.end(), i) == v.end()) {
missing.push_back(i);
}
}
return missing;
}
int main()
{
std::vector<int> arr = { 5, 2, 6 };
std::vector<int> m = missingElements(arr);
copy(m.begin(), m.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
return 0;
}
If you want to do something with lower computational complexity you can have an already filled vector and then mark for removal the elements found. Then it's a good chance to learn the erase–remove idiom:
std::vector<int> missingElements(const std::vector<int> v)
{
std::vector<int> m = { -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (const auto& x: v) {
m[x] = -1;
}
m.erase(remove(m.begin(), m.end(), -1), m.end());
return m;
}
By this approach we are using space to reduce execution time. Here the time complexity is O(N) where N is the no of elements given in the array and space complexity is O(1) i.e 10' .
#include<iostream>
void printMissingElements(int arr[], int n){
// Using 1D dp to solve this
int dp[11] = {0};
for(int i = 0; i < n; i++){
dp[arr[i]] = 1;
}
// Traverse through dp list and check for
// non set indexes
for(int i = 1; i <= 10; i++){
if (dp[i] != 1) std::cout << i << " ";
}
}
int main() {
int arr[] = {5,2,6};
int n = sizeof(arr) / sizeof(int);
printMissingElements(arr, n);
}
void printMissingElements(int arr[], int n,int low, int high)
{
bool range[high - low + 1] = { false };
for (int i = 0; i < n; i++) {
if (low <= arr[i] && arr[i] <= high)
range[arr[i] - low] = true;
}
for (int x = 0; x <= high - low; x++) {
if (range[x] == false)
std:: cout << low + x << " ";
}
}
int main()
{
int arr[] = { 5,2,6,6,6,6,8,10 };
int n = sizeof(arr) / sizeof(arr[0]);
int low = 1, high = 10;
printMissingElements(arr, n, low, high);
return 0;
}
I think this will work:
vector<int> missingnumbers(vector<int> A, int N)
{ vector<int> v;
for(int i=1;i<=10;i++)
v.push_back(i);
sort(A.begin(),A.end());
int j=0;
while(j<v.size()) {
if(binary_search(A.begin(),A.end(),v[j]))
v.erase(v.begin()+j);
else
j++;
}
return v;
}

Is this a wrong approach to find whether array is subarray of another array?

bool isSubset(int arr1[], int m,int arr2[], int n){
set<int> hashset;
for (int i = 0; i < m; i++){
hashset.insert(arr1[i]);
}
for (int i = 0; i < n; i++) {
if (hashset.find(arr2[i]) == hashset.end())
return false;
}
return true;
}
Is this correct method to find whether arr2 is sub array of arr1 or not
because sub array is contiguous part of array but this code is not checking for any order that's why I want to be sure.
Is this correct method to find whether arr2 is sub array of arr1 or not
No, it isn't. Your method doesn't consider the order of elements. It is more of a method to find whether a bunch of numbers (given in arr2) exist in an arr1.
For instance, if int arr1[] = {1, 2, 3} and int arr2[] = {2, 1}, the method you implemented will return true, while it should return false.
Here is how you would do it:
#include <iostream>
bool isSubset(int array[], int m, int subarray[], int n)
{
if (n > m)
return false;
for (int i = 0; i <= m-n; i++) {
int ii = i, j;
for (j = 0; j < n; j++)
if (subarray[j] != array[ii])
break;
else
ii++;
if (j == n)
return true;
}
return false;
}
Then call it like this:
int main()
{
int array[] = {1, 2, 3};
const int m = sizeof(array) / sizeof(*array);
int subarray1[] = {1, 2};
const int n1 = sizeof(subarray1) / sizeof(*subarray1);
int subarray2[] = {2, 1};
const int n2 = sizeof(subarray2) / sizeof(*subarray2);
std::cout << isSubset(array, m, subarray1, n1) << "\n"; // Will print 1
std::cout << isSubset(array, m, subarray2, n1) << "\n"; // Will print 0
}
You understood that the way your code is checking subarray is wrong.
A suggestion-
Use of C language style array in C++ is discouraged. Instead, you should use the appropriate standard container, provided in Containers library. You can use std::array container in place of plain C style array. Below is the sample code to check subarray:
#include <iostream>
#include <array>
#include <algorithm>
int main () {
std::array<int,12> arr1 {9,5,2,5,9,2,4,7,0,4,5,1};
std::array<int,3> arr2 {5,9,2};
bool res = false;
size_t pos = 0;
std::array<int,12>::iterator x;
while ((x = std::find(arr1.begin() + pos, arr1.end(), arr2[0])) != arr1.end()) {
size_t currpos = x - arr1.begin();
if ((arr1.size() - currpos >= arr2.size()) &&
((std::equal(arr1.begin() + currpos, arr1.begin() + currpos + arr2.size(), arr2.begin())))) {
res = true;
break;
}
pos = currpos + 1;
}
if (res) {
std::cout << "arr2 is subarray of arr1" << std::endl;
} else {
std::cout << "arr2 is not subarray of arr1" << std::endl;
}
return 0;
}

Debugging Problem - I'm getting random outputs from a C++ program

It is a very simple code that should solve the Cut Rod Optimization Problem. Most of the time it outputs the correct output but sometimes it gives random answers. I don't know what might be causing this.
Code:
#include <iostream>
#include <limits>
int cutRod(int p[], int n);
int max(int a, int b);
int main()
{
int n = 10;
int p[n] = {1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
int numOfCuts = cutRod(p, n);
std::cout << "Cuts: " << numOfCuts << std::endl;
return 0;
}
int cutRod(int p[], int n)
{
if (n == 0)
{
return 0;
}
int q = INT32_MIN;
for (int i = 0; i <= n; ++i)
{
q = max(q, p[i] + cutRod(p, n-i-1));
}
return q;
}
int max(int a, int b){
if (a >= b)
{
return a;
}
else if (b > a)
{
return b;
}
}
How to regenerate error:
Just run the program a couple of times. Most of the times, it gives 30 as answer. Which is correct. But other times, it will give a random big number as an output.
for (int i = 0; i <= n; ++i)
{
q = max(q, p[i] + cutRod(p, n-i-1));
}
here you are calling p[n] which is out of index but in c++ array it still lets you access that memory block having a garbage value, so you are basically adding a garbage value with returned value of function.
in array you will have valid value upto only 0 to n - 1 for p,
I guess this is the thing that is causing the problem

Im currently learning about algorithms in one of my CS classes. I am trying to write a code for QuickSort

Like the title says, I am trying to write a code for QuickSort, but I am trying to do this following a psuedocode given to us in the lecture. This isn't an assignment that's due it's just me trying to figure it out on my own. I've found a sample of QuickSort online, but it looks different than what our psuedocode says. The QuickSort code i found online uses pointers, i don't think pointers are mentioned in the given psuedocode. In other words, could someone check if im on the right path and maybe point out where I messed up. Thank you!
My code
#include <iostream>
using namespace std;
int Partition(int arr[], int p, int r)
{
int x = arr[r];
int i = p - 1;
for (int j = p; j < r - 1; j++)
{
if (arr[j] <= x)
{
i = i + 1;
swap(arr[i], arr[j]);
}
swap(arr[i + 1], arr[r]);
}
return i + 1;
}
void Quicksort(int arr[], int p, int r)
{
if (p < r)
{
int k = Partition(arr, p, r);
Quicksort(arr, p, k - 1);
Quicksort(arr, k + 1, r);
}
}
void print(int arr[], int n)
{
int i;
for (i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
}
int main()
{
int arr[] = { 5, 3, 4, 9, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
Quicksort(arr, 0, n);
print(arr, n);
//I get an error here "Stack around the variable 'arr' was corrupted"
}
This is the psuedocode for my QuickSort function
Picture number two is the given psuedocode for my Partition function
In Partition(), if i is never incremented, then a swap(arr[p-1], ...) is done, probably the cause of the stack error. Normally, quick sort parameters are first and last index, as opposed to first and end (= last+1) index, in this case, Quicksort(arr, 0, n-1). The inner loop is looking for values < pivot (not <= pivot). The final swap needs to be done after the for loop. Fixes noted in comments.
#include <iostream>
using namespace std;
int Partition(int arr[], int p, int r)
{
int x = arr[r];
int i = p; // fix
for (int j = p; j < r; j++) // fix
{
if (arr[j] < x) // fix
{
swap(arr[i], arr[j]);
i = i + 1; // fix
}
}
swap(arr[i], arr[r]); // fix
return i; // fix
}
void Quicksort(int arr[], int p, int r)
{
if (p < r)
{
int k = Partition(arr, p, r);
Quicksort(arr, p, k - 1);
Quicksort(arr, k + 1, r);
}
}
void print(int arr[], int n)
{
int i;
for (i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
}
int main()
{
int arr[] = { 5, 3, 4, 9, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
Quicksort(arr, 0, n-1); // fix
print(arr, n);
return 0; // fix
}

I have written a quick sort code and logic seem pretty correct but there is no output on the console

I have written a quick sort code and logic seem pretty correct but there is no output on the console.
when only index function runs the output is correct and also the output loop is correct but when quicSort function is added then there is no output.
#include <iostream>
using namespace std;
int index(int* a, int s, int e) {
int i, j, start, piv, temp;
start = s;
piv = a[e];
for (i = start; i <= e; i++) {
if (a[i] <= piv) {
temp = a[i];
a[i] = a[start];
a[start] = temp;
start++;
}
}
return start;
}
void quickSort(int* a, int s, int e) {
int pivot;
if (s < e) {
pivot = index(a, s, e);
quickSort(a, s, pivot - 1);
quickSort(a, pivot + 1, e);
}
}
int main() {
int A[] = {2, 5, 8, 3, 6, 9, 1, 4};
quickSort(A, 0, 7);
for (int i = 0; i < 8; i++) {
cout << A[i];
}
return 0;
}
the output should be sorted array
Code needs two fixes. Changes noted in comments:
#include <iostream>
using namespace std;
int index(int* a, int s, int e) {
int i, start, piv; // j, temp not used
start = s;
piv = a[e];
for (i = start; i <= e; i++) {
if (a[i] < piv) { // fix (not <=)
swap(a[i], a[start]); // simplify
start++;
}
}
swap(a[start], a[e]); // fix (swap pivot into place)
return start;
}
void quickSort(int* a, int s, int e) {
int pivot;
if (s < e) {
pivot = index(a, s, e);
quickSort(a, s, pivot - 1);
quickSort(a, pivot + 1, e);
}
}
int main() {
int A[] = {2, 5, 8, 3, 6, 9, 1, 4};
quickSort(A, 0, 7);
for (int i = 0; i < 8; i++) {
cout << A[i] << " "; // put space beteen numbers
}
cout << endl;
return 0;
}
I think you get confused by bubblesort when creating your quicksort program.
The quicksort ideia is to break the vector in smaller vectors one with the numbers bigger than the pivot e another with the numbers smaller than the pivot.
You should round up your code in C++ data structures like vectors.
One example is, with c++11:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
vector<int> quicksort(vector<int> data) {
if (data.size() == 1) return data;
vector<int> small_numbers;
vector<int> big_numbers;
vector<int> ret;
float pivot = accumulate(data.begin(), data.end(), 0.0) / data.size();
for (int value : data) {
if (value < pivot) {
small_numbers.push_back(value);
} else {
big_numbers.push_back(value);
}
}
if (small_numbers.empty()) return big_numbers;
small_numbers = quicksort(small_numbers);
big_numbers = quicksort(big_numbers);
ret.insert(ret.end(), small_numbers.begin(), small_numbers.end());
ret.insert(ret.end(), big_numbers.begin(), big_numbers.end());
return ret;
}
int main() {
vector<int> A({2, 5, 8, 3, 6, 9, 1, 4});
A = quicksort(A);
for (int value : A) cout << value << endl;
return 0;
}
This example break the the vector into two vectors, the pivot is the mean value of the values of vector. It calls the function recursively until it calls a vector with the size of 1 element.
Hope it push you to a less complicated way of see quicksort.