Quick sort algorithm code - c++

I'm trying to implement a quick sort that sorts numbers and words based on the number value. I can't seem to figure out how to fix the following code to work right.
if (high!=low&& high>low)//compares hashes and finds the number in the middle. swaps hashes and corresponding words
{
long one=hash[low];
long two=hash[high];
long three = hash[high/2];
if((one<=two&&one>=three)||(one<=three&&one>=two))
{
swap(hash[low], hash[high]);
swap(copyOfWords[low], copyOfWords[high]);
}
else if((three<=one&&three>=two)||(three<=two&&three>=one))
{
swap(hash[high/2], hash[high]);
swap(copyOfWords[high/2], copyOfWords[high]);
}
else
{
}
int i=low;
int j=high-1;
while(i!=j&&i<j)
{
while(hash[i]<hash[high]&&i<j)// find higher numbers and lower numbers then the middlle and swaps them
{
i++;
}
while(hash[j]>hash[high]&&i<j)
{
j--;
}
if(i==j||i>j)
{
}
else
{
swap(hash[i],hash[j]);
swap(copyOfWords[i],copyOfWords[j]);
i++;
j--;
}
}
swap(hash[i],hash[high]);
swap(copyOfWords[i], copyOfWords[high]);
quickSort(low, j-1);//recursive
quickSort(j+1, high);
}
}
I know the values in hash and copyOfWords are correct because when I use shell sort, it sorts them the right way. for example if there are two words, copyOfWOrds[0]="1994," and copyOfWords[1]="a" then hash[0]=549456039 and hash[1]=197000000, but the sort puts them a 1994, a instead of a 1994,. It causes more problems with more elements. Any help would be appreciated. Thanks

Why don't you go to the quick sort wiki page and see how it's done?
Your code tries to do unnecessary stuffs and eventually trips over its own feet. Keep it simple and it will work.
And Btw Quicksort works very well on arrays, so it's a shame to make one version where the array is hard-coded.

Related

Find the next palindrome

Given a number, I am trying to find the smallest palindrome number greater than given number. Here is my code:
#include<bits/stdc++.h>
using namespace std;
char a[1000005];
int main(){
int t,len,ni,nj,nk,i,j,k;
cin>>t;
while(t--){
cin>>a;
char ch=getchar();
len=strlen(a);
k=len-1;
for(i=0;i<len;i++){
if(a[i]!='9'){
break;
}
}
if(i==len){ //if all digits are 9
for(i=len-1;i>0;i--){
a[i]='0';
}
a[0]='1';
a[len]='1';
a[len+1]='\0';
}
else{
for(i=0;i<len/2;i++){
if(a[i]!=a[len-1-i]){ //check if number is already palindrome
break;
}
}
if(i==len/2){ //add 1 if it is already palindrome
j=len-1;
while(1){
nj=((int)a[j])-48;
nj++;
if(nj<10){
a[j]=nj+48;
break;
}
else{
a[j]=48;
j--;
}
}
}
for(i=0;i<len/2;i++){
if(a[i]==a[k]){ //compare first with last,second with second last...
k--;
}
else{
nk=((int)a[k])-48;
ni=((int)a[i])-48;
if(nk<ni){
a[k]=ni+48;
}
else{
j=k; a[j]=ni+48; j--;
while(1){
nj=((int)a[j])-48;
nj++;
if(nj<10){
a[j]=nj+48;
break;
}
else{
a[j]=48;
j--;
}
}
if(j<=i){
i=j-1;
k=len-j;
}
}
k--;
}
}
if(len%2==0){
a[len/2]=a[len/2-1];
}
}
cout<<a<<endl;
}
return 0;
}
My code is working fine for all the inputs I have tried, but it is not getting accepted. Is my code right?
Some of the reasons why this code might have been rejected are:
length of code: finding the smallest palindromic number greater than a given input can be done with a lot less code.
memory efficiency: ~1MB of memory is by far too much for operations that can easily be done in-place. The total memory required would simply be the size of the number plus a few additional integer-vars.
runtime efficiency: This problem could be solved in O(n), where n is the number of digits of the number. I don't quite get the way your code works - and to be honest I won't put any effort in understanding that mess -, but that doesn't exactly look linear (or even close to it).
#include <bits/stdc++.h>: This header is GNU-specific, compiler-specific, ... . This code might not even compile if the tester uses another compiler. Apart from that the compilation takes more time with this header and will produce a larger executable than if you'd simply include the required headers. The reasons why it's a bad idea to use this header are described here in a more extensive way.
I can only speculate about the reason(s) why the solution really was rejected. The least information required to answer this would be a link to the judge that rejected it - which should aswell give a reason why it was rejected.

Chain of doughnut - codechef

I am trying to solve this problem since last two days. I am not getting the correct results.
The solutions which are accepted are sorting the number of chains first. I didn't understand why they do it.
Just the first task is correct. For Second task the answer is wrong and for third time limit exceeds.
Here is my code:
#include<iostream>
using namespace std;
int main() {
int t;
cin>>t;
while(t--) {
long n=0;
int f=0,c=0,cuts=0;
cin>>n>>c;
int toJoint=c-1;
int A[c];
for (int i =0;i<c;i++)
cin>>A[i];
if (c>2){
for (int i =0;i<c;i++) {
if (A[i]==1) {
f++;
cuts++;
toJoint-=2;
if(toJoint<=1) break;
}
}
if (toJoint>0){
if (f==0) cout<<toJoint<<endl;
else cout<<(cuts+toJoint)<<endl;
}
else cout<<cuts<<endl;
}
else if (c==1) cout<<0<<endl;
else cout<<++cuts<<endl;
}
return 0;
}
You have the following operations, each of which can be used to link two chains together:
Cut a chain (>=3) in the middle (0 less chains)
Cut a chain (>=2) at the end (1 less chain)
Cut a single donut (2 less chains)
An optimal solution never needs to use (1), thus the objective is to make sure that as many operations as possible are (3)s, the rest being (2)s. The obvious best way to do this is to repeatedly cut a donut from the end of the smallest chain and use it to stick together the biggest two chains. This is the reason for sorting the chains. Even so, it might be faster to make the lengths into a heap, and only extract the minimum element as many times as we need to.
Now to the question: your algorithm only uses operation (3) on single donuts, but doesn't try to make more single donuts by cutting donuts from the end of the smallest chain. And so as Jarod42 points out, with
counterexample, it isn't optimal.
I should also point out that your use of VLAs
int A[c];
is an non-standard extension. To be strict, you should use std::vector instead.
For completeness, here's an example:
std::sort(A.begin(), A.end());
int smallest_index = 0;
int cuts = 0;
while (M > 1)
{
int smallest = A[smallest_index];
if (smallest <= M - 2)
{
// Obliterate the smallest chain, using all its donuts to link other chains
smallest_index++;
M -= smallest + 1;
cuts += smallest;
}
else
{
// Cut M - 2 donuts from the smallest chain - linking the other chains into one.
// Now there are two chains, requiring one more cut to link
cuts += M - 1;
break;
}
}
return cuts;
(disclaimer: only tested on the sample data, may fail in corner-cases or not work at all.)

Program to find greatest common divisor

Here's a c++ program i tried to write for the above question.Our teacher told us to use a for loop.
void main()
int A[30],B[30],m,n,i,j,x,z;
cout<< "enter two numbers";
cin>>m>>n;
for(i=1,j=0;i<=m,j<30;i++,j++)
{
if(m%i==0)
{ A[j]=i;
z=j;
}
}
for(i=1,j=0;i<=n,j<30;i++,j++)
{
if(n%i==0)
{ B[j]=i;
x=j;
}
}
for(i=z;i>=0;--i)
{
for(j=x;j>=0;--j)
{
if(A[i]==B[j])
{ cout<<"gcd="<<A[i];
}
}
}
}
The output displays " Enter two numbers:" and when i entered 15 and 3, the result i got was a blinking cursor. Working through the program, I realised that the divisors for each number when stored in the arrays of A and B were not stored continuously or had gaps in between. If there isn't anything in the memory for say A[11], what happens when you check it against another variable with a number? Can somebody please modify this to make it work and tell me what's wrong? I am new to programming, so excuse my program if it is clumsy.
Andreas has pointed out that there are other ways to achieve the goal of finding the gcd, but the point of the exercise is to get a better handle on some basic programming constructs. So lets go with your approach.
Your idea is to compute the two lists of divisors and then compare them. As you say, having a list with gaps in makes this harder.
So adapt your loop, only increment the storage index when you've stored something
for(i=1,j=0;i<=m && j<30;i++) // need the && here; a comma means something different
{
if(m%i==0)
{ A[j++]=i;
z=j;
}
}
Second, you have a typo you're not storing in B, so fix that
for(i=1,j=0;i<=n && j<30;i++)
{
if(n%i==0)
{ B[j++]=i; //B here not A
x=j;
}
}
That should help.
Try this:
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
As taken from here: https://codereview.stackexchange.com/questions/66711/greatest-common-divisor

How to efficiently sort an array of doubles without libraries?

I'm looking for an efficient way to sort an array of doubles. I know bubble sort and selection sort, neither of them seems to be fast enough. I read about quick sort, but I don't understand how it works. There are a lots of example source codes, but all of them are poorly commented. Can someone explain it to me?
I wrote this after getting an idea about how qsort works. I do think qsort is not that easy to understand. It would probably need some optimalization, and is probably no where compared to the original qsort, but here it is. Thanks for peaple who tried to help with this.
/*recursive sorting, throws smaller values to left,
bigger to right side, than recursively sorts the two sides.*/
void sort(double szam[], int eleje, int vege){
if (vege > eleje + 1){ //if I have at least two numbers
double kuszob = szam[eleje]; //compare values to this.
int l = eleje + 1; //biggest index that is on the left.
int r = vege; //smallest index that is on the right side.
while (l < r){ //if I haven't processed everything.
if (szam[l] <= kuszob) l++; //good, this remains on the left.
else
swap(&szam[l], &szam[--r]); //swap it with the farthest value we haven't checked.
}
swap(&szam[--l], &szam[eleje]); //make sure we don't compare to this again, that could cause STACK OVERFLOW
sort(szam, eleje, l); //sort left side
sort(szam, r, vege); //sort right side
}
return; //if I have 1 number break recursion.
}

Numberofcomparison and nunber of item movements

Im using c++ and is using insertion sort
Where in the insertion sort algoithm should we put a counter to monitor number of item movements and number of item comparison. I have included my setup below
void InsertionSort::insertion_sort()
{
int key,i,count = 0;
for(int j=1;j<10;j++)
{
key=Arr1[j];
i=j-1;
while(Arr1[i]>key && i>=0)
{
Arr1[i+1]=Arr1[i];
i--;
numberOfItemMovements++;
}
Arr1[i+1]=key;
}
}
}
as you can see, i cant seem to figure out where comparison counter should be put, although the item movement counter is good and work as expected. thanks
A way of getting this to work is using numberOfComparisons in the loop.
while(++numberOfComparisons && Arr1[i]>key && i>=0)
{
Arr1[i+1]=Arr1[i];
numberOfItemMovements++;
i--;
}
1) Do you understand why ++numberOfComparisons can be used in the while loop but numberOfComparisons++ would fail?
2) You have a problem where Arr1[-1] could be evaluated. Can you figure out where this is happening and how you can change your code to fix it?
The movement counter is indeed correct.
In order to implement the comparison counter, you need to restructure your code a bit. In particular, you need to be able to distinguish between Arr1[i]>key and i>=0, since one of them entails a comparison while the other doesn't.
Since this looks like homework, I'll leave the rest for you to figure out.