QuickSort for vector<string> - c++

I'm new to recursion and get kind of confused by it this is my first time coding Quick Sort for a string I keep getting an error. Does anyone know where I messed up?
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
void SwapValue(string &a, string &b)
{
string t = a;
a = b;
b = t;
}
void quicksort(vector<string> &list, int first, int end)
{
int l = first;
int r = end;
int pivot = ((first + end) / 2);
while (l <= r)
{
while (list[l] <= (list[pivot]))
++l;
while (list[r] >= (list[pivot]))
--r;
if (l <= r)
{
swap(list[l], list[r]);
++l;
--r;
}
}
if (first <= r)
quicksort(list, first, r);
if (end >= l)
quicksort(list, l, end);
}
void print(vector <string> const &a)
{
cout << "[ ";
for(int i=0; i < a.size(); i++)
{
cout << a[i] << ' ';
}
cout << ']';
}
int main()
{
vector<string> test = {"Bob", "Andrew", "Joe"};
quicksort(test, 0, test.size()-1);
print(test);
return 0;
}
I thought about getting the ASCII values of the first char within the string but I would have to use a nested forloop to retrieve the character and wouldn't that make QuickSort slower?

This statement:
while (list[l] <= (pivot))
How does that even compile? Comparing a string to an integer?
I suspect you mean:
while (list[l] <= list[pivot])
Similar treatment is also needed for the while (list[r] >= (pivot)) statement. And I don't think you want to use >= on the right side.
while (i <= r)
That won't compile either since i is not defined. I suspect you meant l, not 'i'.

Related

Solving String Factoring

I'm trying to solve a question from kattis as shown here regarding string factorisation. I've tried adjusting my code for quite abit but it still seems theoretically correct. Not sure why it still fails for some of the test cases.
#include <stdio.h>
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
string shortener (string input) {
map<string, int> freq;
int flag = 0;
for (int i = (input.length())/2; i >= 1 && !flag; i--) {
for (int d = 0; d + i + i <= input.length(); d++) {
if (input.substr(d, i) == input.substr(d + i, i)) {
freq[input.substr(d,i)]++;
flag = 1; // stop at this size
}
}
}
int largest = 0;
if (freq.empty()) return input;
//string largest;
auto x = max_element(freq.begin(), freq.end(),
[](const pair<string, int>& p1, const pair<string, int>& p2) {
return p1.second < p2.second; });
if (x->first == input) return input;
int a = input.find(x->first);
for (int i = 0; i < x->second ; i++) {
input.replace(a, x->first.length(), "");
a = input.find(x->first);
}
if (a != -1) {
if (!input.substr(0, a).empty())
input.replace(0, a, shortener(input.substr(0, a)));
if (!input.substr(a + x->first.length()-1, input.length()-1).empty())
input.replace(a + x->first.length()-1, input.length()-1, shortener(input.substr(a + x->first.length()-1, input.length()-1)));
//cout << input.substr(a + x->first.length()-1, input.length()-1) << endl;
input.replace(a, x->first.length(), shortener(x->first));
}
return input;
}
int main () {
string input;
cin >> input;
cout << shortener(input).length() << endl;
}
I know my code may not be the most efficient, but I'm hoping to find out what kind of test case might potentially break my code.

Quicksort 3 way partition too slow

I am using quicksort 3 way partition, but it is turning out to be too slow as and when the vector size is greater than 10000.
What am I doing wrong? Please guide me! Any help will be appreciated
The answer should be computed in less than 2.2 sec.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
using std::vector;
using std::swap;
void print(vector<int> v)
{
for(int i = 0; i < v.size(); i++) std::cout << v[i] << " ";
std::cout << std::endl;
}
void partition2(vector<int> &a, int l, int r, int &i, int &j) {
int k;
int middle=(l+r)/2;
/*Selecting pivot as median of low, high and middle*/
if(((a[l]<=a[middle]) && (a[middle]<=a[r])) || ((a[r]<=a[middle]) && (a[middle]<=a[l])))
k=middle;
else if(((a[middle]<=a[l]) && (a[l]<=a[r])) || ((a[r]<=a[l]) && (a[l]<=a[middle])))
k=l;
else if(((a[middle]<=a[r]) && (a[r]<=a[l])) || ((a[l]<=a[r]) && (a[r]<=a[middle])))
k=r;
swap(a[l], a[k]);
//print(a);
int low_value = a[l];
int index_low = l;
int index_high = l;
int counter=l;
for (int i = l + 1; i <= r; i++) {
if (a[i] < low_value) {
swap(a[i], a[index_low]);
counter++;
low_value=a[l];
}
else if(a[i]==low_value)
{
index_high++;
swap(a[i], a[index_high]);
}
//print(a);
}
i=counter;
j=index_high;
//swap(a[l], a[j]);
//return j;
}
void randomized_quick_sort(vector<int> &a, int l, int r) {
if (l >= r) {
return;
}
int i,j;
partition2(a, l, r, i, j);
randomized_quick_sort(a, l, i-1);
randomized_quick_sort(a, j+1, r);
}
int main() {
int n;
std::cin >> n;
//while(1){
//n=100+rand()%99999;
//std::cout<<n<<std::endl;
vector<int> a(n);
for (size_t i = 0; i < a.size(); ++i) {
std::cin >> a[i];
//a[i]=1+rand()%99999999;
}
randomized_quick_sort(a, 0, a.size() - 1);
for (size_t i = 0; i < a.size(); ++i) {
std::cout << a[i] << ' ';
}
//std::cout<<"Pass\n";
//}
return 0;
}
Everything at first glance is correct. However, there are probably just too many comparison operations. Try this option - it works on my computer for 1.6 seconds on average.
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <ctime>
#include <random>
#include <chrono>
#include <iomanip>
using namespace std;
using namespace std::chrono;
//======= quick_sort =======//
template<typename T>
int partition(vector<T>& numbers, const int& left, const int& right)
{
swap(numbers[left], numbers[left + (right - left) / 2]);
T mid = numbers[left];
int i(left + 1), j(right);
while (i <= j)
{
while ( i <= j && numbers[i] <= mid ) i++;
while ( i <= j && numbers[j] > mid ) j--;
if ( i < j ) swap(numbers[i], numbers[j]);
}
swap(numbers[i - 1], numbers[left]);
return i - 1;
}
template<typename T>
void quick_sort_rec(vector<T>& numbers, const int& left, const int& right)
{
if (left >= right) return;
int p = partition(numbers, left, right);
quick_sort_rec(numbers, left , p - 1);
quick_sort_rec(numbers, p + 1 , right);
}
//=========================//
template<typename T>
T random_T(long min, long max)
{
return (T)min + static_cast<T>(rand()) / (static_cast<T>(RAND_MAX / ((T)(max - min))));
}
template<typename T>
float time_func(void (*f)(vector<T>&, const int&, const int&), vector<T>& a)
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
f(a, 0, a.size() - 1);
high_resolution_clock::time_point t2 = high_resolution_clock::now();
return 1000.0 * (duration_cast<microseconds>(t2 - t1).count()) / (float)(CLOCKS_PER_SEC); /// CLOCKS_PER_SEC;
}
int main()
{
srand((unsigned)(777));
vector<int> a;
for (int i = 0; i < 10000; i++)
{
a.push_back(random_T<int>(0, 1000));
}
cout << setprecision(10) << "quick sort rec = " << time_func(quick_sort_rec, a) << endl;
return 0;
}
I run the following code to test partition2
int main(){
vector<int> a = {2, 1, 1, 9, 5, 3, 4, 2, 7};
int i, j;
partition2(a, 0, a.size() - 1, i, j);
for (auto i : a)
cout << i << ' ';
cout << '\n';
return 0;
}
And the results are
1 1 5 9 2 3 4 2 7
If the partition2 selecting median of low, high and middle as pivot, then the pivot should be 5 and the results should be something like
2 1 1 3 4 2 5 9 7
Then I check the code
if (a[i] < low_value) {
swap(a[i], a[index_low]);
counter++;
low_value=a[l];
}
else if(a[i]==low_value)
{
index_high++;
swap(a[i], a[index_high]);
}
It seems to be that the code try to find the minimum value of array and then move them to beginning of array. It seems that it is doing selection sort instead of quicksort. It explains why it is slow when input size is large.

std::vector out of range for min-heap: C++

I've neglected to work on this code (or any other coding projects) for a while, so while I know what is basically wrong with the code, I've been having a hard time finding exactly where the vector is going out of range. I've been running gdb on it all morning to no avail. I'm trying to make a min-heap out of a vector "theData" in C++.
#include <iostream>
#include <vector>
#include <algorithm>
using std::vector;
using std::cin;
using std::cout;
using std::swap;
using std::pair;
using std::make_pair;
class HeapBuilder {
private:
vector<int> data_;
vector< pair<int, int> > swaps_;
void WriteResponse() const {
cout << swaps_.size() << "\n";
for (int i = 0; i < swaps_.size(); ++i) {
cout << swaps_[i].first << " " << swaps_[i].second << "\n";
}
}
void ReadData() {
int n;
cin >> n;
data_.resize(n);
for(int i = 0; i < n; ++i)
cin >> data_[i];
}
void makeMinHeap(vector<int> &theData, int i, int n) {
int minIndex;
int left = 2*i;
int right = 2*i + 1;
if (left < n && theData.at(left) < theData.at(i)) {
minIndex = left;
}
else if (right < n && theData.at(right) < theData.at(i)) {
minIndex = right;
}
if (minIndex != i) {
swap(theData.at(i), theData.at(minIndex));
swaps_.push_back(make_pair(i, minIndex));
makeMinHeap(theData, minIndex, n);
}
}
void GenerateSwaps() {
swaps_.clear();
int size = data_.size();
for (int i = (size/2); i >= 0; i--) {
makeMinHeap(data_, i, size);
}
}
public:
void Solve() {
ReadData();
GenerateSwaps();
WriteResponse();
}
};
int main() {
std::ios_base::sync_with_stdio(false);
HeapBuilder heap_builder;
heap_builder.Solve();
return 0;
}
You are not putting in a check for minIndex.
Look what happens when your left<=n and right <=n both fails, most likely when the whole recursion is about to stop, since you just check
minIndex != i
// ^-- default each time is garbage which in case last>n && right>n leaves it garbage
// hence when it comes to
if(minIndex!=i){
// It's actually true where it was suppose to break out n thus throws out_of_range
}
Quick n easy solution would be to add a flagcheck
bool flagcheck = false;
if(){ flagcheck = true; }
else if(){ flagcheck = true; }
if(minIndex!=i && flagcheck){}

Can't understand why my program throws error

My code is in
#include <iostream>
#include <string>
#include <algorithm>
#include <climits>
#include <vector>
#include <cmath>
using namespace std;
struct State {
int v;
const State *rest;
void dump() const {
if(rest) {
cout << ' ' << v;
rest->dump();
} else {
cout << endl;
}
}
State() : v(0), rest(0) {}
State(int _v, const State &_rest) : v(_v), rest(&_rest) {}
};
void ss(int *ip, int *end, int target, const State &state) {
if(target < 0) return; // assuming we don't allow any negatives
if(ip==end && target==0) {
state.dump();
return;
}
if(ip==end)
return;
{ // without the first one
ss(ip+1, end, target, state);
}
{ // with the first one
int first = *ip;
ss(ip+1, end, target-first, State(first, state));
}
}
vector<int> get_primes(int N) {
int size = floor(0.5 * (N - 3)) + 1;
vector<int> primes;
primes.push_back(2);
vector<bool> is_prime(size, true);
for(long i = 0; i < size; ++i) {
if(is_prime[i]) {
int p = (i << 1) + 3;
primes.push_back(p);
// sieving from p^2, whose index is 2i^2 + 6i + 3
for (long j = ((i * i) << 1) + 6 * i + 3; j < size; j += p) {
is_prime[j] = false;
}
}
}
}
int main() {
int N;
cin >> N;
vector<int> primes = get_primes(N);
int a[primes.size()];
for (int i = 0; i < primes.size(); ++i) {
a[i] = primes[i];
}
int * start = &a[0];
int * end = start + sizeof(a) / sizeof(a[0]);
ss(start, end, N, State());
}
It takes one input N (int), and gets the vector of all prime numbers smaller than N.
Then, it finds the number of unique sets from the vector that adds up to N.
The get_primes(N) works, but the other one doesn't.
I borrowed the other code from
How to find all matching numbers, that sums to 'N' in a given array
Please help me.. I just want the number of unique sets.
You've forgotten to return primes; at the end of your get_primes() function.
I'm guessing the problem is:
vector<int> get_primes(int N) {
// ...
return primes; // missing this line
}
As-is, you're just writing some junk here:
vector<int> primes = get_primes(N);
it's undefined behavior - which in this case manifests itself as crashing.

Build Max Heap algorithm won't work

I am trying to build a max heap using the algorithm given in Introduction to Algorithms, and I can't get it to work. Firstly, I'm having some interesting issues with passing arrays between functions. My understanding is that arrays are passed by reference in C++, but after I pass an array and I check the addresses of the argument and the parameter they don't match. When I try to use sizeof() on an array that is a parameter it doesn't return the correct value.
Secondly, the algorithm just doesn't seem to work. It does make some changes to the array, and gets the numbers closer to a heap but still has a ways to go. I've checked the code dozens of times and it seems to be spot on with pseudo code given in my text. What am I missing?
#include <iostream>
#include <ctime>
#define N 10
#define DISPLAY
using namespace std;
// Display an array
void display(double p[]) {
#ifdef DISPLAY
for (int i = 0; i < N; i++) cout << p[i] << " ";
cout << endl;
#endif
}
inline int parent(int i)
{return i/2;}
inline int left(int i)
{return 2*i;}
inline int right(int i)
{return 2*i+1;}
void maxHeapify(double p[], int i)
{
int largest;
int l = left(i);
int r = right(i);
if (l <= N && (p[l] > p[i]))
largest = l;
else
largest = i;
if (r <= N && (p[r] > p[largest]))
largest = r;
if (largest != i)
{
double temp = p[i];
p[i] = p[largest];
p[largest] = temp;
maxHeapify(p, largest);
}
}
void buildMaxHeap(double p[])
{
for (int i=N/2; i>0; i--)
maxHeapify(p, i);
}
int main() {
double a[] = {4,1,3,2,16,9,10,14,8,7};
buildMaxHeap(a);
display(a);
}
I modified your code as below:
#include <iostream>
#include <ctime>
#define N 10
#define DISPLAY
using namespace std;
// Display an array
void display(double p[]) {
#ifdef DISPLAY
for (int i = 0; i < N; i++) cout << p[i] << " ";
cout << endl;
#endif
}
inline int parent(int i)
{return i/2;}
inline int left(int i)
{return 2*i;}
inline int right(int i)
{return 2*i+1;}
void maxHeapify(double p[], int i)
{
int largest;
int l = left(i)-1;
int r = right(i)-1;
i=i-1;
if (l <= N && (p[l] > p[i]))
largest = l;
else
largest = i;
if (r <= N && (p[r] > p[largest]))
largest = r;
if (largest != i)
{
double temp = p[i];
p[i] = p[largest];
p[largest] = temp;
maxHeapify(p, largest+1);
}
}
void buildMaxHeap(double p[])
{
for (int i=N/2; i>0; i--)
maxHeapify(p, i);
}
int main() {
double a[] = {4,1,3,2,16,9,10,14,8,7};
buildMaxHeap(a);
display(a);
}