Quicksort algorithm issue - c++

Having a problem with my quicksort algorithm. The code compiles without any errors, but when I try to run the program the only output I get is "The random numbers are: " and then acts like it wants input from the user, and then I have to kill the program. Now when I remove the call for my quicksort function in my main program, the program prints out the numbers, but doesn't work with the call for quicksort function. I'm not sure if the parameters I'm using are the issue or if it's the function itself.
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <stack>
#include <queue>
using namespace std;
void quicksort(int arr[], int left, int right) {
int l = left;
int r = right;
int tmp;
int pivot = arr[(left + right) / 2];
while (l <= r) {
while (arr[l] < pivot)
l++;
while (arr[l] > pivot)
r--;
if (l <= r) {
tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
l++;
r--;
}
}
if (left < r)
quicksort(arr, left, r);
if (l < right)
quicksort(arr, r, right);
}
int main() {
int n = 20;
int testlist[n];
for (int i = 0; i<n; i++) {
testlist[i] = rand()%100;
}
cout << "The random numbers are: " << endl;
for (int i = 0; i < n; i++) cout << testlist[i] << " ";
quicksort(testlist, 0, n - 1);
cout << " " << endl;
cout << "The sorted numbers are: " << endl;
for (int i = 0; i < n; i++) {
cout << testlist[i] << " ";
}
return 0;
}

You have an infinite loop in your quicksort function. As this function never returns, nothing after the "The random numbers are:" line is printed, as the quicksort call never returns. The random numbers themselves may or may not print (and do print on my system) as the system is not guaranteed to flush the output buffer to the screen immediately. (They probably would be printed if you wrote a std::endl to cout after the for loop that prints the numbers.)
I suspect this is the problem:
while (arr[l] > pivot)
r--;
That statement while (arr[l] > pivot) should probably actually be while (arr[r] > pivot).

This happens because something goes wrong inside quicksort() and you print the numbers without an std::endl!
You see, without the std::endl, the numbers are written in the output buffer, but they are not flushed. They will, eventually, without the std::endl, but that your code doesn't make it to that time.
Pro tip: Always use std::endl when you debug your code!
I won't debug your quicksort(), since you should do that, in order to practice! If you need a reference, you can always use my baby example: Quicksort (C++), which is written in a c-like way, so that people from both c and c++ can easily follow! :)
Hunch: You use recursion, your program doesn't terminate...Infinite loop may be the cause... ;)
BTW, if I were you and didn't have any important reason to use:
#if __INCLUDE_LEVEL__ < 1
I would discard that (along with the accompanied #endif).

Related

Trying to make a program that automatically sorts an array before using binary searching

I'm trying to make a program that asks the user to input a set of 10 numbers before asking them to select a number from the list. it would first automatically sort the ten numbers before being placed in a binary searching function.
Here's the code I wrote.
#include <iostream>
using namespace std;
int searchbinary(int arr[], int left, int right, int x){
while (left <= right){
int mid = left+(right-left)/2;
if (arr[mid]==x){
return mid;
}
else if (arr[mid]<1){
left = mid + 1;
}
else{
right = mid -1;
}
}
return -1;
}
int main(){
int num;
int darr[10];
int output;
int temp;
cout << "Enter 10 Numbers: " << endl;
for (int i=0; i<10; i++){
cin >> darr[i];
}
for (int i=0;i<10;i++){
for (int j=i+1;j<10;j++){
if (darr[i]>darr[j]){
temp = darr[i];
darr[i] = darr[j];
darr[j] = temp;
}
}
}
cout << "Enter a number from list: ";
cin >> num;
output = searchbinary(darr, 0, 9, num);
if (output ==-1){
cout << "Match not Found";
}
else {
cout << "Match Found in Position " << output;
}
return 0;
}
It works fine when I do it separately, but combining the two seems to cause an issue. Any suggestions?
Well, there seems to be a problem with your Binary Search. In the else if condition you wrote arr[mid] < 1 whereas it should have been arr[mid] < x because you are trying to find x not 1. Bellow is the code that should work:
#include <iostream>
using namespace std;
//binary search
int searchbinary(int arr[], int left, int right, int x){
while (left <= right){
int mid = (right+left)/2;//this formula is better than the one you used, it has the same results though
if (arr[mid] == x){
return mid;
}
else if (arr[mid] < x) {//here was your mistake,it is x not 1
left = mid + 1;
}
else{
right = mid -1;
}
}
return -1;
}
int main(){
int num;
int darr[10];
int output;
int temp;
cout << "Enter 10 Numbers: " << endl;
//input
for (int i=0; i<10; i++){
cin >> darr[i];
}
//sorting
for (int i=0;i<10;i++) {
for (int j=i+1;j<10;j++) {
if (darr[i]>darr[j]) {
temp = darr[i];
darr[i] = darr[j];
darr[j] = temp;
}
}
}
cout << "Enter a number from list: ";
cin >> num;
output = searchbinary(darr, 0, 9, num);//searching
//output
if (output == -1){
cout << "Match not Found";
}
else {
cout << "Match Found in Position " << output;
}
return 0;
}
If you fix that issue then your code should work but I would like to point some things out:
It is better not to hardcode numbers, like when you write 10 as a limit to all for loops. It would be better to save 10 in a variable or use darr.length().
Instead of using your own Sort you could have used the built-in sort that the algorithm library provides like this sort(darr, darr+10). In this case it was only with 10 elements but bear in mind that if you ever find yourself trying to solve the same problem with array sizes up to a million or more, the sort you implemented(it is called Bubble sort), would take up to much time, whereas std::sort would be able to do it faster as it has been optimised.
In this problem first sorting the array and then using Binary Search on top of it takes more time than performing Linear Search on the unsorted array. Generally, when searching once for a value on an unsorted array, first sorting it and then using Binary Search takes up more time than just doing Linear Search no matter the size of the array. However, if you wanted to to use the array in the future multiple times then your approach could prove to be faster.
These are all small improvements that you could make to your code but I am guessing this is done for educational purposes that is why you didn't do some of them.

Randomly Shuffle an array and using quick sort algorithm

I have been trying to write a code to randomly shuffle the array elements, and then use the quick sort algorithm on the array elements. This is the code I wrote:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void randomise(int arr[], int s, int e)
{
int j;
srand(time(NULL));
for (int i = e; i >= s; i--)
{
int j = rand() % (i + 1);
swap(&arr[i], &arr[j]);
}
}
int Partition(int arr[], int s, int e)
{
int pivot = arr[e];
int i = s - 1;
int j;
for (j = s; j <= e; j++)
{
if (arr[j] <= pivot)
{
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[e]);
return i + 1;
}
void QuickSort(int arr[], int s, int e)
{
if (s >= e)
return;
int x = Partition(arr, s, e);
QuickSort(arr, s, x - 1);
QuickSort(arr, x + 1, e);
}
int main()
{
int b[] = {1, 2, 3, 4, 5};
randomise(b, 0, 4);
cout << "Elements of randomised array are:";
for (int i = 0; i <= 4; i++)
{
cout << b[i] << endl;
}
QuickSort(b, 0, 4);
cout << "Elements after quick sort are:";
for (int i = 0; i <= 4; i++)
{
cout << b[i] << endl;
}
return 0;
}
However, on debugging on GDB, I found out that this program gives segmentation fault. On execution, this program gives the output as:
Elements of randomised array are:4
5
2
3
1
Can someone tell me what is the bug in this code (I have tried debugging it on GDB, but I am still clueless).
Basically, when the error is segmentation fault, you should be looking for a bug which you will feel like crashing your head into wall, after finding it. On line 26. change <=, to < . It's in your partition function. for (j = s; j < e; j++)
A little explanation about quick sort; After each time quickSort function runs on a partiotion, the last element of the partition, called pivot, will reach its' real place in array. The partition function, returns the real place of the pivot in the array. Then the main array will be split into two more partitions, before the pivot place, and after that. Your bug is returning real-pivot-place + 1, as the output of partition function. So you will run quickSort on wrong partition; the partition that is already sorted but the program will keep trying to sort it over and over because of wrong partitioning. As you may know, each time you run a function, its' variables will be saved into a stack in computer. Since your calling a recursive function over and over(that isn't supposed to stop), this stack will get full and will overflow. After that, computer will represent some undefined behavior and maybe throw an exception that can not describe the problem correctly. This is why your getting segmentation fault. But why you return real-pivot-place + 1? Because in your for loop in partition function, you will visit the pivot too, which you shouldn't. Because pivot isn't supposed to be compared with itself. So you will increase i variable unnecessarily. https://en.wikipedia.org/wiki/Call_stack Check this link for additional information about stack and how a function runs in computer.

Averaging Coin Tosses with Accumulator C++

This is the problem I am working with
Using a loop and rand(), simulate a coin toss 10000 times
Calculate the difference between heads and tails.
Wrap the above two lines in another loop, which loops 1000 times.
Use an accumulator to sum up the differences
Calculate and display the average difference between the number of heads and tails.
The accumulator is not working the way I want It to? Very much a C++ Noob, for homework lol. Anyone help please?
Why am I using rand()????
second part of the assignment has us using the newer method (mt19937), just trying to tackle this bit first before moving on.
#include <iostream>
using namespace std;
int main() {
int heads = 0, tails = 0, num, total = 0;
srand(time(NULL));
for (int h = 0; h < 1000; h++) // Loop Coin Toss
{
for (int i = 0; i < 10000; i++) // COIN TOSS
{
int random = rand() % 2;
if (random == 0)
{
heads++;
}
else
{
tails++;
}
}
cout << abs((heads++ - tails++));
cin >> num;
total =+ num;
}
cout << "The average distance between is " << total / 1000 << endl;
cin.get();
return 0;
}
With your code, you never actually save the values that you need. And there's some unnecessary arithmetic that would throw off your results. This line:
cout << abs((heads++ - tails++)); increments the heads and tails variables, but they shouldn't be.
The next two lines make no sense. Why do you need to get a number from the user, and why do you add that number to your total?
Finally, this expression: total / 1000 performs integer division, which will throw off your results.
Those are the immediate issues I can spot in your code.
Next, we move on to your problem statement. What is an accumulator? To me, it sounds like you're supposed to have a class? It also reminds me of std::accumulate, but if that's what you intended, it would have said as much. Also, std::accumulate would require storing results, and that's not really necessary for this program. The code below performs the main task, i.e. it runs the necessary simulations and tracks results.
You'll notice I don't bother counting tails. The big average is also calculated as it goes since the total number of simulations is known ahead of time.
#include <cmath>
#include <iostream>
#include <random>
int flip_coin() {
static std::mt19937 prng(std::random_device{}());
static std::uniform_int_distribution<int> flip(0, 1);
return flip(prng);
}
int main() {
constexpr int tosses = 10'000;
constexpr int simulations = 1'000;
double diffAvg = 0.0;
for (int i = 0; i < simulations; ++i) {
int heads = 0;
for (int j = 0; j < tosses; ++j) {
if (flip_coin()) {
++heads;
}
}
diffAvg +=
std::abs(heads - (tosses - heads)) / static_cast<double>(simulations);
}
std::cout << "The average heads/tails diff is: " << diffAvg << '\n';
return 0;
}
What I ended up doing that seems to work for **THIS VERSION WITH RAND() (using the new method later) **
#include <iostream>
using namespace std;
int main()
{
int heads = 0, tails = 0, total = 0;
srand(time(NULL));
for (int h = 0; h < 1000; h++) // Loop Coin Toss
{
{
for (int i = 0; i < 10000; ++i) // COIN TOSS
if (rand() % 2 == 0)
++heads;
else
++tails;
total += abs(heads - tails);
}
}
cout << "The average distance between is " << total / 1000.0 << '\n';
cin.get();
return 0;
}

Words of length k generation from a DFA

Good day,
I'm having a serious problem into generating a list with all the words of length k (the generate function is the function intended to generate all the words of length k, the other function is used to find out if a word is accepted or not) from a DFA just by using the DFS algorithm, here's my attempt:
#include<vector>
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
vector < pair <int,char> > a[100];
int viz[100], v[100];
char s1[100];
void accepted (int q, char c, char s[100], int x) {
c = s[x];
viz[q] = 1;
cout << q;
for (int i = 0; i < a[q].size(); i++)
if (a[q][i].second == c) {
x++;
accepted (a[q][i].first, a[q][i+1].second, s, x);
}
}
void generate (int q, int k) {
int x = 0;
v[q] = 1;
while (x < k) {
cout << a[q][0].second;
for (int i = 0; i < a[q].size(); i++)
if (v[a[q][i].first] == 0)
{
cout << a[q][i].second;
generate(a[q][i].first, k);
}
x++;
}
}
int main() {
ifstream f ("input.txt");
int n, m, x, y, i, j, k;
char c;
char s[100];
f >> n >> m;
for (i = 0; i < m; i++) {
f >> x >> y;
f >> c;
a[x].push_back (make_pair(y,c));
}
for (i = 0; i < n; i++) {
cout << i << ": ";
for (j = 0; j < a[i].size(); j++)
cout << a[i][j].first << a[i][j].second << " ";
cout << endl;
}
cout << endl << "Fiite states: 2, 3" << endl << endl;
cin.get (s,100);
accepted(0, s[0], s, 0);
if (viz[2] == 1) cout << endl << "Accepted";
cout << endl;
cin >> k;
generate (0, k);
cout << endl;
return 0;
}
Also here's how my input looks like:
4 6
0 0 a
0 1 b
1 2 c
2 2 a
2 3 c
3 3 c
Here's how the DFA and the output would look like:
The serious problem I'm facing is that I can't find a way to ouput properly all the obtained words to the screen by calling the generate function.
I changed your generate function as below. Following that is an explanation as to what I thought and how I changed it.
void generate (int q, int k, string &s) {
if (k > 0) {
for (int i = 0; i < a[q].size(); i++)
{
s += a[q][i].second;
generate(a[q][i].first, k-1, s);
s.pop_back();
}
}
else {
cout << s << endl;
}
}
First and foremost, you were attempting a mixture of recursive and repetitive version of DFS, but you had no structure for keeping the stack if you were, and I doubt, going for a repetitive version using an explicit stack. Basically, your outer while loop was wrong, as the depth should increase as you recursively traverse the graph and not repetitively at a single level of recursion using a while loop as you did. You could also, as I mentioned, have a repetitive approach and use an explicitly defined stack other than the one implicitly used by memory when you implement DFS recursively. But it was easier and more intuitive to get a grasp of DFS with its recursive implementation, so I left out the outer loop.
Secondly, keeping a list of visited nodes is not a good idea as you want to list all k-length strings and your DFA is not a simple graph. (i.e. there may exist edges from node u to node u) So I removed the if statement inside the for loop as you could visit the sane node multiple times. Your approach is exponential based on the branching factor of the DFA, but if your k is small enough, it should work regardless of that. And the approach being exponential is not the problem to the solution of which you are looking with this question.
Thirdly, probably due to your usage of while loop, there was a mixup with printing a single character at each level, which is incorrect. Remember, at every node of depth k, you have to print all the characters you encountered starting from the root of the tree. That is why I added a string as the third parameter to your function. Don't worry, though, it's passed by reference and it will only cause an addition of O(k) space complexity to your algorithm, which should be negligible.
If in your main function you start traversing using the call below, you will find that it works properly.
string S;
generate(0, k, S);

C++ - Calculate execution time of a function always = 0?

I use clock() in library to calculate excution time of a function, which is BubbleSort(..) function in my code below. But probleam is that the return execution time always = 0 (and it shows no unit, too).
This is my code:
#include <iostream>
#include <ctime>
using namespace std;
void BubbleSort(int arr[], int n)
{
for (int i = 1; i<n; i++)
for (int j = n-1; j >=i; j-- )
if (arr[j] < arr[j-1])
{
int temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
}
return;
}
int main()
{
int arr[] = {4,1,7,2,6, 17, 3, 2, 8,1};
int len = sizeof(arr)/sizeof(int);
cout << "Before Bubble Sort: \n";
for (int i=0;i<len;i++)
{
cout << arr[i] << " ";
}
clock_t start_s=clock(); // begin
BubbleSort(arr,len);
clock_t stop_s=clock(); // end
cout << "\nAfter Bubble Sort: \n";
for (int i=0;i<len;i++)
{
cout << arr[i] << " ";
}
// calculate then print out execution time - currently always returns 0 and I don't know why
cout << "\nExecution time: "<< (double)(stop_s - start_s)/CLOCKS_PER_SEC << endl;
//system("pause");
return 0;
}
I haven't known how to fix this problem yet .. So hope you guys can help me with this. Any comments would be very appreciated. Thanks so much in advanced !
As you have only a very small array, the execution time is probably much shorter than the resolution of clock(), so you either have to call the sort algorithm repeatedly or use another time source.
I modified your code as such and both start end stop have the value of 0. (ubuntu 13.10)
std::cout<<"start: "<<start_s<<std::endl;
BubbleSort(arr,len);
clock_t stop_s=clock(); // end
std::cout<<"stop: "<<stop_s<<std::endl;
you probably want something more like gettimeofday()
this http://www.daniweb.com/software-development/cpp/threads/120862/clock-always-returns-0 is an interesting discussion of the same thing. the poster concluded that clock()(on his machine) had a resolution of about 1/100 of a sec. and your code is probably ( almost certainly) running faster than that