My Quicksort does not sort the input array - c++

I tried to write quicksort by myself and faced with problem that my algorithm doesn't work.
This is my code:
#include <iostream>
#include <vector>
using namespace std;
void swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
void qsort(vector <int> a, int first, int last)
{
int f = first, l = last;
int mid = a[(f + l) / 2];
do {
while (a[f] < mid) {
f++;
}
while (a[l] > mid) {
l--;
}
if (f <= l) {
swap(a[f], a[l]);
f++;
l--;
}
} while (f < l);
if (first < l) {
qsort(a, first, l);
}
if (f < last) {
qsort(a, f, last);
}
}
int main()
{
int n;
cin >> n;
vector <int> a;
a.resize(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
qsort(a, 0, n - 1);
for (int i = 0; i < n; i++) {
cout << a[i] << ' ';
}
return 0;
}
My sort is similar to other that described on the Internet and I can't find where I made a mistake.
Even when I change sort function, the problem was not solved.

You don't pass qsort the array you want to sort, you pass it the value of that array. It modifies the value that was passed to it, but that has no effect on the array.
Imagine if you had this code:
void foo(int a)
{
a = a + 1;
}
Do you think if I call this like this foo(4); that foo is somehow going to turn that 4 into a 5? No. It's going to take the value 4 and turn it into the value 5 and then throw it away, since I didn't do anything with the modified value. Similarly:
int f = 4;
foo(f);
This will pass the value 4 to foo, which will increment it and then throw the incremented value away. The value f has after this will still be 4 since nothing ever changed f.
You meant this:
void qsort(vector <int>& a, int first, int last)
Your swap has the same problem. It swaps the values of a and b, but then never does anything with the value of a or b. So it has no effect. How could it? Would swap(3, 4); somehow change that 3 into a 4 and vice-versa? What would that even mean?

Your swap does not swap anything. You should write tests not only for the whole program but for as small pieces as possible. At least you should test single functions. Try this:
int main() {
int a= 42;
int b= 0;
std::cout << "before " << a << " " << b << "\n";
swap(a,b);
std::cout << "after " << a << " " << b << "\n";
}
This is "poor mans testing". For automated tests you should use a testing framework.
Then read about pass by reference. (While doing so you hopefully also realize the issue with not passing the vector to qsort by reference.)
Then use std::swap instead of reinventing a wheel.

I Found two error on your code
void swap(int a, int b) This method is not working, cause is receive value only and swap , but the original one is not updated.
void swap(int *a, int *b)
{
int t;
t = *b;
*b = *a;
*a = t;
}
swap(&a, &b);
And you pass vactor which also pass value. replace your void qsort(vector <int> &a, int first, int last) method.

Related

How to not repeat code in calculation functions?

I have made a simple program that performs basic arithmetic operations on all the elements of a given array. But the problem is that the code is very repetitive and it's not a good practice to write repeated code and I can't come up with a solution to this problem.
How can we minimize code repetition in this program?
int add(int numcount, int numarr[]){
int total = numarr[0];
// add all the numbers in a array
for (int i = 1; i < numcount; i++){
total += numarr[i];
}
return total;
}
int sub(int numcount, int numarr[]) {
int total = numarr[0];
// subtract all the numbers in array
for (int i = 1; i < numcount; i++){
total -= numarr[i];
}
return total;
}
int mul(int numcount, int numarr[]) {
int total = numarr[0];
// multiply all the numbers in array
for (int i = 1; i < numcount; i++){
total *= numarr[i];
}
return total;
}
int main(int argc, char* argv[]){
const int n = 5;
int arr[n] = {1, 2, 3, 4, 5};
cout << "Addition: " << add(n, arr) << endl;
cout << "Subtraction: " << sub(n, arr) << endl;
cout << "Multiplication: " << mul(n, arr) << endl;
}
How can we minimize code repetition in this program?
Generically, by identifying the repeated structure and seeing whether we can either abstract it out, or find an existing name for it.
The repeated structure is just setting the running result to the first element of a container, and using a binary function to combine it with each subsequent element in turn.
Take a look at the Standard Algorithms library and see if any existing function looks similar
std::accumulate can do what we need, without any extra arguments for the add, and with just the appropriate operator function object for the others
So, you can trivially write
int add(int numcount, int numarr[]){
return std::accumulate(numarr, numarr+numcount, 0);
}
// OK, your sub isn't actually trivial
int sub(int numcount, int numarr[]){
return std::accumulate(numarr+1, numarr+numcount, numarr[0],
std::minus<int>{});
}
// could also be this - honestly it's a little hairy
// and making it behave well with an empty array
// requires an extra check. Yuck.
int sub2(int numcount, int numarr[]){
return numarr[0] - add(numcount-1, numarr+1);
}
etc.
It would be slightly nicer to switch to using std::array, or to use ranges if you're allowed C++20 (to abstract iterator pairs over all containers).
If you must use C arrays (and they're not decaying to a pointer on their way through another function), you could write
template <std::size_t N>
int add(int (&numarr)[N]){
return std::accumulate(numarr, numarr+N, 0);
}
to save a bit of boilerplate (passing numcount everywhere is just an opportunity to get it wrong).
NB. as mentioned in the linked docs, std::accumulate is an implementation of a left fold. So, if the standard library didn't provide accumulate, there's still an existing description of the "thing" (the particular "higher-order function") we're abstracting out of the original code, and you could write your own foldl template function taking the same std::plus, std::minus etc. operator functors.
You can use std::accumulate:
auto adder = [](auto accu,auto elem) { return accu + elem; };
auto multiplier = [](auto accu, auto elem) { return accu * elem; };
auto sum = std::accumulate(std::begin(arr),std::end(arr),0,adder);
auto prod = std::accumulate(std::begin(arr),std::end(arr),0,multiplier);
The result of sub is just 2*arr[0] - sum.
Be careful with the inital value for std::accumulate. It determines the return type and multiplying lots of int can easily overflow, perhaps use 0LL rather than 0.
In cases where std::accumulate nor any other standard algorithm fits, and you find yourself writing very similar functions that only differ by one particular operation, you can refactor to pass a functor to one function that lets the caller specifiy what operation to apply:
template <typename F>
void foo(F f) {
std::cout << f(42);
}
int identity(int x) { return x;}
int main() {
foo([](int x) { return x;});
foo(identity);
}
Here foo prints to the console the result of calling some callable with parameter 42. main calls it once with a lambda expression and once with a free function.
How can we minimize code repetition in this program?
One way to do this is to have a parameter of type char representing the operation that needs to be done as shown below:
//second parameter denotes the operator which can be +, - or *
int calc(int numcount, char oper, int numarr[])
{
//do check here that we don't go out of bounds
assert(numcount > 0);
int total = numarr[0];
// do the operatations for all the numbers in the array
for (int i = 1; i < numcount; i++){
total = (oper == '-') * (total - numarr[i]) +
(oper == '+') * (total + numarr[i]) +
(oper == '*') * (total * numarr[i]);
}
return total;
}
int main()
{
int arr[] = {1,2,3,4,5,6};
std::cout << calc(6, '+', arr) << std::endl; //prints 21
std::cout << calc(6, '-', arr) << std::endl; //prints -19
std::cout << calc(6, '*', arr) << std::endl; //prints 720
}
Working demo

Error during implementation of quickSort algorithm in c++:- "error: cannot convert 'int*' to 'int**'....."

The full error is as follows:- "|error: cannot convert 'int*' to 'int**' for argument '1' to 'void quickSort(int**, int, int)'|"
MY whole code is below:
#include <iostream>
using namespace std;
int Partition (int *A[], int p, int r) {
int x = *A[r];
int i = p-1;
for (int j=0; j<=r; j++){
if(*A[j]<=x){
i++;
int save=*A[j];
*A[j] = *A[i];
*A[i] = save;
}
}
int save2=*A[i+1];
*A[i+1]=*A[r];
*A[r]=save2;
return (i+1);
}
void quickSort(int *A[], int p, int r) {
if (p<r){
int q = Partition(A, p, r);
quickSort(A, p, (q-1));
quickSort(A, (q+1), r);
}
}
int main() {
int RR[] = {2,8,7,1,3,5,6,4};
int y=sizeof(RR)/sizeof(int)-1;
cout << y << endl;
int *QQ = RR;
cout << *QQ << endl;
quickSort(QQ, 0, y);
return 0;
}
This is an implementation that I tried myself from a pseudo code. I'm new to programming so it would be a great help if you could illustrate a little of why this error occurred.
Thanks in advance
The first thing I notice about the code is a whole lot of unneccessary pointer dereferencing. The contents of A will be changed without the need for additional pointers because Arrays decay to pointers (What is array decaying?) so A is treated as a pointer to the first array element and you are effectively passing the array by reference already.
Worse, int * A[] isn't a pointer to an array of int, it is an array of pointers to int. A very different thing. *A[0] does not return 2, it tries to use 2 as an address and return whatever happens to be in memory at address 2. This will almost certainly not be anything you want, or are allowed, to see so the program will do something unfortunate. Crash if you are lucky.
Instead, try
int Partition (int A[], int p, int r) {
int x = A[r];
int i = p-1;
for (int j=0; j<=r; j++){
if(A[j]<=x){
i++;
int save=A[j];
A[j] = A[i];
A[i] = save;
}
}
int save2=A[i+1];
A[i+1]=A[r];
A[r]=save2;
return (i+1);
}
void quickSort(int A[], int p, int r) {
cout << p << ',' << r << endl; // Bonus: This will make the next bug really easy to see
if (p<r){
int q = Partition(A, p, r);
quickSort(A, p, (q-1));
quickSort(A, (q+1), r);
}
}
Note the extra cout statement at the top of quickSort This will help you see the logic error in Partition. The program will crash due to a... wait for it! A Stack Overflow, but the cout will show you why.

Implementing quicksort on strings

I'm trying to implement the quicksort on a string of characters. The output should give me an alphabetical order version of the input, however right now it's just giving me the original input. This was an attempt trying to translate the pseudo code from Intro to Algorithm 3rd edition on Quicksort.
Any help would be greatly appreciated, thanks!
Here's the pseudo code of quicksort from the book
#include <string>
#include <iostream>
#include <stdlib.h>
using namespace std;
int partition_str(string A, int start, int finish){
char x = A[finish], temp;
int i = start - 1;
for (int j = start; j <= finish -1; j++){
if (A[j] <= x){
i ++;
temp = A[i]; A[i] = A[j]; A[j] = temp;
}
temp = A[i+1]; A[i+1] = A[finish]; A[finish] = temp;
return i+1;
}
}
string quicksort_char(string A, int start, int finish)
{
if (start < finish)
{
start = partition_str(A, start, finish);
quicksort_char(A, start, finish -1);
quicksort_char(A, start+1, finish);
}
return A;
}
int main(){
string test = "gsgkdsdkjs";
string result = quicksort_char(test, 0, 10);
cout << result << endl;
return 0;
}
In the pseudocode you linked, it mentions that partition() alters subarrays in place. This insinuates that you need to pass by reference, rather than by value. Notice the ampersand (&) I add in the function signature. Your code was passing by value, so it was making a copy of the input string, rather than altering it in place. In your quicksort() function, you wrote the code expecting that A will be altered by the function.
I cleaned up your code a bit here with the intent of making it clearer and look more like the pseudocode...
#include <iostream>
#include <string>
using namespace std;
void exchange(char& a, char& b)
{
char value_of_a = a;
char value_of_b = b;
a = value_of_b;
b = value_of_a;
};
int partition(string& A, int p, int r)
{
char x = A[r];
int i = p-1;
for (int j=p; j<=(r-1); ++j)
{
if (A[j] <= x)
{
i++;
exchange(A[i], A[j]);
}
}
exchange(A[i+1], A[r]);
return i+1;
};
void quicksort(string& A, int p, int r)
{
if (p < r)
{
int q = partition(A, p, r);
quicksort(A, p, q-1);
quicksort(A, q+1, r);
}
};
int main()
{
string input = "gsgkdsdkjs";
cout << "input string: " << input << endl;
quicksort(input, 0, input.size());
cout << "sorted string: " << input << endl;
return 0;
}
In your partition_str() function you pass in string A by value, which makes a copy of A rather than using the same A you passed in. It then performs some operations and returns an integer. The copy of A is then thrown away and your original A variable was never modified. This means that if you want your variable A to be changed, you must pass by reference.
Also, don't be confused by the function argument naming. Your partition_str() function signature is:
int partition_str(string A, int start, int finish)
The fact the 'string A' is defined as an argument does not mean that it is related to any other variable in your code called 'A'. It is merely a way of referring to particular argument that was passed in.

Deleting element from an array in c++

I have read others posts, but they don't answer my problem fully.
I'm learning to delete elements from an array from the book and try to apply that code.
As far as I can grasp I'm passing array wrong or it is sending integer by address(didn't know the meaning behind that).
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(double x[], int& n, int k);
int main()
{
// example of a function
int mass[10]={1,2,3,45,12,87,100,101,999,999};
int len = 10;
for(int i=0;i<10;i++)
{
cout<<mass[i]<<" ";
};
delete_element(mass[10],10&,4);
for(int i=0;i<10;i++)
cout<<mass[i]<<" ";
return 0;
}
void delete_element(double x[], int& n, int k)
{
if(k<1 || k>n)
{
cout<<"Wrong index of k "<<k<<endl;
exit(1); // end program
}
for(int i = k-1;i<n-1;i++)
x[i]=x[i+1];
n--;
}
There are a couple of errors in your code. I highlight some of the major issues in question 1-3:
You call exit, which does not provide proper cleanup of any objects since it's inherited from C. This isn't such a big deal in this program but it will become one.
One proper way too handle such an error is by throwing an exception cout<<"Wrong index of k "<< k <<endl;
exit(1);
Should be something like this:
throw std::runtime_error("invalid index");
and should be handled somewhere else.
You declare function parameters as taking a int& but you call the function like this: delete_element(mass[10],10&,4); 10& is passing the address of 10. Simply pass the value 10 instead.
You are "deleting" a function from a raw C array. This inherently doesn't make sense. You can't actually delete part of such an array. It is of constant compile time size created on the stack. The function itself doesn't do any deleting, try to name the functions something more task-oriented.
You are using C-Arrays. Don't do this unless you have a very good reason. Use std::array or std::vector. These containers know their own size, and vector manages it's own memory and can be re sized with minimal effort. With containers you also have access to the full scope of the STL because of their iterator support.
I suggest you rewrite the code, implementing some type of STL container
Line 15: syntax error
you can't pass a number&
If you want to pass by reference, you need to create a variable first, like:
your delete_element function signature conflicts with your declared arrays. Either use a double array or int array and make sure the signatures match.
delete_element(mass, len , 4);
when you write the name of an array without the brackets, then it's the same as &mass[0]
ie. pointer to the first element.
complete changes should be:
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(int x[], int& n, int k);
int main(){
// example of a function
int mass[10] = { 1, 2, 3, 45, 12, 87, 100, 101, 999, 999 };
int len = 10;
for (int i = 0; i<10; i++){ cout << mass[i] << " "; };
cout << endl;
delete_element(mass, len , 4);
for (int i = 0; i<10; i++)cout << mass[i] << " ";
cout << endl;
cin.ignore();
return 0;
}
void delete_element(int x[], int& n, int k){
if (k<1 || k>n){
cout << "Wrong index of k " << k << endl;
exit(1); // end program
}
for (int i = k - 1; i<n - 1; i++)
x[i] = x[i + 1];
n--;
}
There are a couple of mistakes in your program.
Apart from some syntax issues you are trying to pass an int array to a function which wants a double array.
You cannot pass a lvalue reference of a int literal. What you want is to pass a reference to the length of the int array. see also http://en.cppreference.com/w/cpp/language/reference.
Here is an updated version of your program.
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(int x[], int& n, int k);
int main() {
// example of a function
int mass[10] = { 1,2,3,45,12,87,100,101,999,999 };
int len = 10;
for (int i = 0;i < len;i++)
cout << mass[i] << " "; ;
cout << endl;
delete_element(mass, len, 4);
for (int i = 0;i < len;i++) // len is 9 now
cout << mass[i] << " ";
cout << endl;
return 0;
}
void delete_element(int x[], int& n, int k) {
if (k<1 || k>n) {
cout << "Wrong index of k " << k << endl;
exit(1); // end program
}
for (int i = k - 1;i<n - 1;i++)
x[i] = x[i + 1];
n--;
}
Although it does not answer your question directly, I would like to show you how you can use C++ to solve your problem in a simpler way.
#include <vector>
#include <iostream>
void delete_element(std::vector<int>& v, const unsigned i)
{
if (i < v.size())
v.erase(v.begin() + i);
else
std::cout << "Index " << i << " out of bounds" << std::endl;
}
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7};
delete_element(v, 4);
for (int i : v)
std::cout << i << std::endl;
return 0;
}
You cannot delete elements from an array, since an array's size is fixed. Given this, the implementation of delete_element can be done with just a single call to the appropriate algorithm function std::copy.
In addition, I highly suggest you make the element to delete a 0-based value, and not 1-based.
Another note: don't call exit() in the middle of a function call.
#include <algorithm>
//...
void delete_element(int x[], int& n, int k)
{
if (k < 0 || k > n-1 )
{
cout << "Wrong index of k " << k << endl;
return;
}
std::copy(x + k + 1, x + n, x + k);
n--;
}
Live Example removing first element
The std::copy call moves the elements from the source range (defined by the element after k and the last item (denoted by n)) to the destination range (the element at k). Since the destination is not within the source range, the std::copy call works correctly.

Making a square() function without x*x in C++

I am self-studying C++ and the book "Programming-Principles and Practices Using C++" by Bjarne Stroustrup. One of the "Try This" asks this:
Implement square() without using the multiplication operator; that is, do the x*x by repeated addition (start a
variable result at 0 and add x to it x times). Then run some version of “the first program” using that square().
Basically, I need to make a square(int x) function that will return the square of it without using the multiplication operator. I so far have this:
int square(int x)
{
int i = 0;
for(int counter = 0; counter < x; ++counter)
{
i = i + x;
}
return i;
}
But I was wondering if there was a better way to do this. The above function works, but I am highly sure it is not the best way to do it. Any help?
Mats Petersson stole the idea out of my head even before I thought to think it.
#include <iostream>
template <typename T>
T square(T x) {
if(x < 0) x = T(0)-x;
T sum{0}, s{x};
while(s) {
if(s & 1) sum += x;
x <<= 1;
s >>= 1;
}
return sum;
}
int main() {
auto sq = square(80);
std::cout << sq << "\n";
}
int square(int x) {
int result = { 0 };
int *ptr = &result;
for (int i = 0; i < x; i++) {
*ptr = *ptr + x;
}
return *ptr;
}
I am reading that book atm. Here is my solution.
int square(int x)
{
int result = 0;
for (int counter = 0; counter < x; ++counter) result += x;
return result;
}
int square(int n)
{
// handle negative input
if (n<0) n = -n;
// Initialize result
int res = n;
// Add n to res n-1 times
for (int i=1; i<n; i++)
res += n;
return res;
}
//Josef.L
//Without using multiplication operators.
int square (int a){
int b = 0; int c =0;
//I don't need to input value for a, because as a function it already did it for me.
/*while(b != a){
b ++;
c = c + a;}*/
for(int b = 0; b != a; b++){ //reduce the workload.
c = c +a;
//Interesting, for every time b is not equal to a, it will add one to its value:
//In the same time, when it add one new c = old c + input value will repeat again.
//Hence when be is equal to a, c which intially is 0 already add to a for a time.
//Therefore, it is same thing as saying a * a.
}
return c;
}
int main(void){
int a;
cin >>a;
cout <<"Square of: "<<a<< " is "<<square(a)<<endl;
return 0;
}
//intricate.
In term of the running time complexity,your implementation is clear and simply enough,its running time is T(n)=Θ(n) for input n elements.Of course you also can use Divide-and-Conquer method,assuming split n elements to n/2:n/2,and finally recursive compute it then sum up two parts,that running time will be like
T(n)=2T(n/2)+Θ(n)=Θ(nlgn),we can find its running time complexity become worse than your implementation.
You can include <math.h> or <cmath> and use its sqrt() function:
#include <iostream>
#include <math.h>
int square(int);
int main()
{
int no;
std::cin >> no;
std::cout << square(no);
return 0;
}
int square(int no)
{
return pow(no, 2);
}