How do I sort an array without using a loop in C++? I think it might use recursion, but I do not know how to implement it.
Use std::sort defined in algorithm header file
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[]={5,3,4,1,2};
sort(a,a+5);
for(int i=0;i<5;i++)
cout<<a[i]<<" "; // 1 2 3 4 5
return 0;
}
//C++
void bubblesort(vector<int> &arr, int iteration) {
if(iteration == 0)
return;
bubbleswap(arr, 0, 1, iteration);
bubblesort(arr, iteration-1);
}
void bubbleswap(vector<int> &arr, int i, int j, int n) {
if(j>=n)
return ;
if(arr[i] < arr[j]){
swap(arr[i], arr[j]);
}
bubbleswap(arr, i+1, j+1, n);
}
void sort(vector<int> &arr) {
int n = arr.size();
if(n<=1)
return ;
bubblesort(arr, n);
}
Recursive Selection Sort
#include <iostream>
#include <vector>
using namespace std;
//----------------------------------------------------------
int recursive_min(vector<int>& a, size_t first) {
//base case
if (first + 1 >= a.size()) {
return first;
}
else {
size_t min_index {first};
int temp_index {recursive_min(a, first + 1)};
if (a[min_index] > a[temp_index]) {
min_index = temp_index;
}
return min_index;
}
}
//----------------------------------------------------------
void selectionSort(vector<int>& a, size_t step = 0) {
//base case
if (step + 1 >= a.size()) {
return;
}
else {
int temp_index {recursive_min(a, step + 1)};
if (a[step] > a[temp_index]) {
swap(a[step], a[temp_index]);
}
selectionSort(a, step + 1);
}
}
//---------------------------------------------------------
int main() {
vector<int> vec {11, 23, 2, 50, 3, 8, 1, 4, 5};
selectionSort(vec);
for (int i : vec) {
cout << i << " ";
}
}
Recursive Insertion Sort
#include <iostream>
#include <vector>
using namespace std;
int recursive_insert(vector<int>& a, int key, int i) {
//base case
if (i <= -1 || a[i] <= key) {
return i;
}
else {
a[i + 1] = a[i];
return recursive_insert(a, key, i - 1);
}
}
//-----------------------------------------------------------------------------
void insertion_sort(vector<int>& a, size_t j = 1) {
//base case
if (j >= a.size()) {
return;
}
else {
int key = a[j];
int i = recursive_insert(a, a[j], j - 1);
a[i + 1] = key;
insertion_sort(a, j + 1);
}
}
//-----------------------------------------------------------------------------
int main() {
vector<int> vec {11, 23, 2, 50, 3, 8, 1, 4, 5};
insertion_sort(vec);
for (int i : vec) {
cout << i << " ";
}
}
#include<stdio.h>
int * sort(int *p,int i,int j,int size)
{
if(i<size)
{
if(j<size-i-1)
{
if(p[j]>p[j+1])
{
int temp = p[j];
p[j] = p[j+1];
p[j+1] = temp;
}
}
else
{
j=-1;
++i;
}
p = sort(p,i,++j,size);
}
return p;
}
Below is how to use it
int main()
{
int array[] ={1,5,2,7,3};
int len = sizeof(array)/sizeof(int);
int *a = sort(array,0,0,len);
for(int i=0;i<len;i++)
{
printf("\n array[%d]->%d",i,a[i]);
}
}
I think you are looking for the Quicksort Algorithm
There are more ways to sort an array.
If you are trying to implement a loop recursively, you can check out a wikipedia article. It is well explained under "Recursion computer science".
Otherwise you can try to implement different sorting algorithms. The well known are Quicksort and Mergesort.
There are many sorting algorithms
Well, I'm writing a Python interpreter and didn't write loop yet. I got the codebase from some website and rewrite the loop by some recursion. It works. :D
def quickSort(arr, low, high):
def jLoop(low, high, pivot, i, j):
if j >= high:
temp = arr[high]
arr[high] = arr[i+1]
arr[i+1] = temp
return (i+1)
else:
if arr[j] <= pivot:
i = i+1
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
return jLoop(low, high, pivot, i, j+1)
def partition(low, high):
i = (low - 1)
pivot = arr[high]
return jLoop(low, high, pivot, i, low)
def quick(low, high):
if low < high:
pi = partition(low, high)
quick(low, pi-1)
quick(pi+1, high)
quick(low, high)
return arr
my_list = [0, 6, 3, 1, 2, 4, 7, 5]
length = 8
print quickSort(my_list, 0, 7)
my_list = [9, 0, 8, 1, 7, 2, 6, 3, 5, 4]
length = 10
print quickSort(my_list, 0, 9)
Related
I am stuck and a simple yet crazy search algorithm. I want to find the index of an element from an array calling a function. The problem is that although the element is already there, the function returns -1; which is supposed to return only if the element is not there.
This is the code:
#include <iostream>
using namespace std;
int search(int arr[], int size, int val, bool left) {
int res;
for (int i = 0; i < size; i++) {
if(val == arr[i]) {
res = i;
break;
}
else if(val != arr[i]) {
res = -1;
}
}
return -1;
}
int main() {
int arr[] = {1, 4, 6, 5, 2, 7, 10, 4};
int size = sizeof(arr) / sizeof(arr[0]);
cout << search(arr,size,6, true) << endl;
return 0;
}
Thanks in advance.
Try Return res from the function
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int search(int arr[], int size, int val, bool left) {
int res = -1;
for (int i = 0; i < size; i++) {
if(val == arr[i]) {
res = i;
break;
}
}
return res;
}
int main() {
int arr[] = {1, 4, 6, 5, 2, 7, 10, 4};
int size = sizeof(arr) / sizeof(arr[0]);
cout << search(arr,size,6, true) << endl;
return 0;
}
for (int i = 0; i < size; i++) {
if(val == arr[i]) {
res = i;
break;
}
else if(val != arr[i]) {
res = -1;
}
}
return -1;
You are returning -1 outside of for loop even when the element is present.
Initialize res variable above for loop and return it
res = -1
After for loop
return res
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.
I am writing a C++ program that finds the number of inversions in a vector using merge sort. An inversion happens when the i'th element is greater than the j'th element, where i < j. For example, say the vector is { 1, 3, 5, 2 }, then there are 2 inversions: {3,2} and {5,2}.
The countNsort function keeps recursing and dividing the vector until the length of the subvector is only one element. The countNsortSplit function performs merge sort to sort and count the number of inversions.
I tried:
Different ways of initializing the input vector. vector<int> a{2,1};, vector<int> a; a={2,1};, and vector<int> a(2); a={2,1};.
Different ways of splitting the input vector into subvectors. vector<int> c(a.begin()+half, a.begin()+n); and vector<int> c(a.begin()+half, a.end());, where n is the size of the vector.
Different IDEs. Atoms gives me this: bash: line 1: 13763 Segmentation fault: 11 /tmp/cpp.out [Finished in 20.57s], CodeBlocks gives me this: error: expected expression for this line: a={2,1}:.
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
struct returnVal {
int count;
vector<int> sorted_array;
};
returnVal countNsortSplit(vector<int> left, vector<int> right, int n) {
returnVal output;
int count = 0;
vector<int> merge;
int i = 0;
int j = 0;
for (int k = 0; k < n; k++) {
if (left[i] < right[j]) {
merge[k] = left[i];
i++;
} else {
merge[k] = right[j];
j++;
// increment count by the # of remaining elements in left
count += left.size()-i;
}
}
output.sorted_array = merge;
output.count = count;
return output;
}
returnVal countNsort(vector<int> a, int n) {
returnVal output;
if (n == 1) {
output.sorted_array = a;
output.count = 0;
return output;
} else {
returnVal left;
returnVal right;
returnVal split;
int half = n / 2;
vector<int> b(a.begin(), a.begin() + half);
vector<int> c(a.begin() + half, a.begin() + n);
left = countNsort(b, half);
right = countNsort(c, n - half); // need n-n/2 in case of odd length
split = countNsortSplit(left.sorted_array, right.sorted_array, n);
output.sorted_array = split.sorted_array;
output.count = left.count + right.count + split.count;
return output;
}
}
int main() {
vector<int> a(2);
//a = {1,3,5,2};
//a = {1,3,5,2,4,6};
a = {2, 1};
returnVal result;
result = countNsort(a, a.size());
cout << result.count << endl;
}
There are multiple problems in you code:
You do not define the destination vector with the proper size
You do not test if i or j have reached to size of the left and right vectors respectively.
The initializer for vector a in main() has an invalid syntax.
Note that you do not need to pass the vector sizes to countNsort and countNsortSplit.
Here is a corrected version:
#include <iostream>
#include <vector>
using namespace std;
struct returnVal {
int count;
vector<int> sorted_array;
};
returnVal countNsortMerge(vector<int> left, vector<int> right) {
int leftSize = left.size();
int rightSize = right.size();
int n = leftSize + rightSize;
int count = 0;
vector<int> merge(n);
int i = 0;
int j = 0;
for (int k = 0; k < n; k++) {
if (i < leftSize && (j == rightSize || left[i] < right[j])) {
merge[k] = left[i++];
} else {
merge[k] = right[j++];
// increment count by the # of remaining elements in left
count += leftSize - i;
}
}
returnVal output;
output.sorted_array = merge;
output.count = count;
return output;
}
returnVal countNsort(vector<int> a) {
int n = a.size();
if (n <= 1) {
returnVal output;
output.sorted_array = a;
output.count = 0;
return output;
} else {
int half = n / 2;
vector<int> b(a.begin(), a.begin() + half);
vector<int> c(a.begin() + half, a.begin() + n);
returnVal left = countNsort(b);
returnVal right = countNsort(c);
returnVal result = countNsortMerge(left.sorted_array, right.sorted_array);
result.count += left.count + right.count;
return result;
}
}
int main() {
//int values[] = { 1, 3, 5, 2 };
//int values[] = { 2, 1 };
int values[] = { 1, 3, 5, 2, 4, 6 };
vector<int> a(values, values + sizeof values / sizeof *values);
returnVal result = countNsort(a);
cout << result.count << endl;
return 0;
}
Note however that it would be more efficient and idiomatic to sort the vector in place and return the inversion count:
#include <iostream>
#include <vector>
size_t countNsortMerge(std::vector<int>& a, size_t start, size_t middle, size_t end) {
std::vector<int> temp(a.begin() + start, a.begin() + middle);
size_t i = 0;
size_t leftSize = middle - start;
size_t j = middle;
size_t count = 0;
for (size_t k = start; k < end; k++) {
if (i < leftSize && (j == end || temp[i] < a[j])) {
a[k] = temp[i++];
} else {
a[k] = a[j++];
// increment count by the # of remaining elements in left
count += leftSize - i;
}
}
return count;
}
size_t countNsort(std::vector<int>& a, size_t start, size_t end) {
if (end - start <= 1) {
return 0;
} else {
size_t middle = start + (end - start) / 2;
size_t leftCount = countNsort(a, start, middle);
size_t rightCount = countNsort(a, middle, end);
return leftCount + rightCount + countNsortMerge(a, start, middle, end);
}
}
int main() {
//int values[] = { 1, 3, 5, 2 };
//int values[] = { 2, 1 };
int values[] = { 1, 3, 5, 2, 4, 6 };
std::vector<int> a(values, values + sizeof values / sizeof *values);
size_t result = countNsort(a, 0, a.size());
std::cout << result << std::endl;
return 0;
}
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.
I've been trying to get this done but i'm stuck right now. Can anyone please recommend the easiest way to get it done? Thank you
c[i] = a[i] + b[i];
// The snippet of code I have above works fine with operator: + - / *
// a[i] = { 1, 8, 13, 15 }
// b[i] = { 3, 8, 13, 20 }
// then c[i] = { 4, 16, 26, 35 }
// But how do i find the union and intersection of both arrays?
// I want the results to look like:
// union = {1,3,8,13,15,20}
// intersection = {8,13}
since you asked for easiest way.
you can put the elements of the arrays into 2 std::set
std::set<T> set1(begin(array1), end(array1));
std::set<T> set2(begin(array2), end(array2));
Then use std::set_union and std::set_intersection in 2 new std::set.
Please take a look at the way its done in these links set union and set intersection
Thus STL takes care of most of the logic and containers.
Try this..
//Unioin of 2 array
#include<stdio.h>
int printUnion(int arr1[], int arr2[], int m, int n)
{
int i = 0, j = 0;
while(i < m && j < n)
{
if(arr1[i] < arr2[j])
printf(" %d ", arr1[i++]);
else if(arr2[j] < arr1[i])
printf(" %d ", arr2[j++]);
else
{
printf(" %d ", arr2[j++]);
i++;
}
}
while(i < m)
printf(" %d ", arr1[i++]);
while(j < n)
printf(" %d ", arr2[j++]);
}
int main()
{
int arr1[] = {1, 8, 13, 15};
int arr2[] = {3, 8, 13, 20};
int m = sizeof(arr1)/sizeof(arr1[0]);
int n = sizeof(arr2)/sizeof(arr2[0]);
printUnion(arr1, arr2, m, n);
getchar();
return 0;
}
//Intersection of two array
#include<stdio.h>
int printIntersection(int arr1[], int arr2[], int m, int n)
{
int i = 0, j = 0;
while(i < m && j < n)
{
if(arr1[i] < arr2[j])
i++;
else if(arr2[j] < arr1[i])
j++;
else /* if arr1[i] == arr2[j] */
{
printf(" %d ", arr2[j++]);
i++;
}
}
}
int main()
{
int arr1[] = {1, 8, 13, 15};
int arr2[] = {3, 8, 13, 20};
int m = sizeof(arr1)/sizeof(arr1[0]);
int n = sizeof(arr2)/sizeof(arr2[0]);
printIntersection(arr1, arr2, m, n);
getchar();
return 0;
}