Lomuto Partition in Quick Sort - algorithm

All of the Lomuto Partion implementations of Quick Sort have two swaps. Can we just use one swap, and delete the swap codes that outside the for loop? When j == high, the code can swap arr[high] with arr[i]. Following is my code:
1. Original LomutoPartion() implementation:
int lomutoPartition(int arr[], int low, int high)
{
int pivot = arr[high];
int i = (low-1);
for (int j = low; j < high; j++)
{
if (arr[j] <= pivot)
{
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[high - 1];
arr[high - 1] = arr[i];
arr[i] = temp;
return i;
}
2. My LomutoPartition() implementation:
int lomutoPartition(int arr[], int low, int high)
{
int pivot = arr[high];
int i = (low-1);
for (int j = low; j <= high; j++)
{
if (arr[j] <= pivot)
{
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
return i;
}

Related

Quick sort -- What am i doing wrong?

Trying to do Quick sort.
logic -> maintaining two variables to place pivot element at correct index. Taking 1st element as pivot. int i for RHS of pivot and Int j for LHS, if they cross each other then j is correct index for pivot.
#include<iostream>
using namespace std;
int partition(int arr[], int low, int high){
int pivot = arr[low];
int i = low+1;
int j = high;
while (i<j)
{
while(arr[i]<=pivot) i++;
while(arr[j]> pivot) j--;
if(i<j) {
swap(arr[i], arr[j]);
}
swap(arr[j], arr[low]);
return j;
}
}
void QuickSort(int arr[], int low , int high){
if(low >= high ) return;
if(high>low){
int pivotindx = partition(arr, low , high);
QuickSort(arr,low, pivotindx-1);
QuickSort( arr, pivotindx+1, high);
}
}
void printquicksort(int arr[] , int n){
cout << " Quick SORT IS HERE BROOOO " << endl;
for (int i = 0; i < n; i++)
{
cout << " " << arr[i] << " " ;
}
}
int main()
{
int arr []={3,4,5,1};
int n= sizeof (arr)/ sizeof (arr[0]);
QuickSort(arr,0,n-1);
printquicksort(arr,n);
return 0;
}
Using i and j for LHS and RHS is type of Hoare partition scheme. The code has a potential issue when using low for the pivot, the while(arr[i]<=pivot) i++; may never encounter an element > pivot and scan past the end of the array. For Hoare partition scheme, the pivot and elements equal to the pivot can end up anywhere, and the partition index separate elements <= pivot and elements >= pivot, so the index needs to be included in one of the recursive calls. Example of a post-increment and post-decrement version of Hoare with the partition code included in QuickSort:
void QuickSort(int *a, int lo, int hi)
{
int i, j;
int p, t;
if(lo >= hi)
return;
p = a[lo + (hi-lo)/2];
i = lo;
j = hi;
while (i <= j){
while (a[i] < p)i++;
while (a[j] > p)j--;
if (i > j)
break;
t = a[i]; // swap
a[i] = a[j];
a[j] = t;
i++;
j--;
}
QuickSort(a, lo, j);
QuickSort(a, i, hi);
}
Example of a classic pre-increment and pre-decrement version of Hoare with the partition code included in QuickSort:
void QuickSort(int a[], int lo, int hi)
{
if(lo >= hi)
return;
int p = a[lo+(hi-lo)/2];
int i = lo-1;
int j = hi+1;
int t;
while(1){
while (a[++i] < p);
while (a[--j] > p);
if(i >= j)
break;
t = a[i]; // swap
a[i] = a[j];
a[j] = t;
}
i = j++;
QuickSort(a, lo, i);
QuickSort(a, j, hi);
}

This is merge sort program. I am getting confused in logic at mergesort function

This is the merge sort program. I am getting confused in logic at mergesort function where low = 0 and high = 6
in the if statement. if(0<6) then go inside it and mid = (0+6)/2= 3;
then it's again calling mergesort fucntion with giving the value to the low=0 and mid=3; than mergesort will call giving the value to low=0 and high =3; and again this will calls continously and hit the last when 0<1 and then the statement will never gets false Am I right please help me.
#include <stdio.h>
void printArray(int *A, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", A[i]);
}
printf("\n");
}
void merge(int A[], int mid, int low, int high)
{
int i, j, k, B[100];
i = low;
j = mid + 1;
k = low;
while (i <= mid && j <= high)
{
if (A[i] < A[j])
{
B[k] = A[i];
i++;
k++;
}
else
{
B[k] = A[j];
j++;
k++;
}
}
while (i <= mid)
{
B[k] = A[i];
k++;
i++;
}
while (j <= high)
{
B[k] = A[j];
k++;
j++;
}
for (int i = low; i <= high; i++)
{
A[i] = B[i];
}
}
void mergeSort(int A[], int low, int high)
{
int mid;
if (low < high)
{
mid = (low + high) / 2;
mergeSort(A, low, mid);
mergeSort(A, mid + 1, high);
merge(A, mid, low, high);
}
}
int main()
{
// int A[] = {9, 14, 4, 8, 7, 5, 6};
int A[] = {9, 1, 4, 14, 4, 15, 6};
int n = 7;
printArray(A, n);
mergeSort(A, 0, 6);
printArray(A, n);
return 0;
}

Runtime error for large inputs for sorting ( quicksort)

This is a very simple program where the user inputs (x,y) coordinates and distance 'd' and the program has to find out the number of unrepeated coordinates from (x,y) to (x+d,y).
For eg: if input for one test case is: 4,9,2 then the unrepeated coordinates are (4,9),(5,9) and (6,9)(x=4,y=9,d=2). I have used a sorting algorithm as mentioned in the question (to keep track of multiple occurrences) however the program shows runtime error for test cases beyond 30. Is there any mistake in the code or is it an issue with my compiler?
For a detailed explanation of question: https://www.hackerearth.com/practice/algorithms/sorting/merge-sort/practice-problems/algorithm/missing-soldiers-december-easy-easy/
#include <stdio.h>
#include <stdlib.h>
int partition(int *arr, int p, int r) {
int x;
x = arr[r];
int tmp;
int i = p - 1;
for (int j = p; j <= r - 1; ++j) {
if (arr[j] <= x) {
i = i + 1;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
tmp = arr[i + 1];
arr[i + 1] = arr[r];
arr[r] = tmp;
return (i + 1);
}
void quicksort(int *arr, int p, int r) {
int q;
if (p < r) {
q = partition(arr, p, r);
quicksort(arr, p, q - 1);
quicksort(arr, q + 1, r);
}
}
int count(int A[],int ct) {
int cnt = 0;
for (int i = 0; i < ct; ++i) {
if (A[i] != A[i + 1]) {
cnt++;
}
}
return cnt;
}
int main() {
int t;
scanf("%d", &t);
long int tmp, y, d;
int ct = 0;
int i = 0;
int x[1000];
int j = 0;
for (int l = 0; l < t; ++l) {
scanf("%d%d%d", &tmp, &y, &d);
ct = ct + d + 1; //this counts the total no of coordinates for each (x,y,d)
for (int i = 0; i <= d; ++i) {
x[j] = tmp + i; //storing all possible the x and x+d coordinates
j++;
}
}
int cnt;
int p = ct - 1;
quicksort(x, 0, p); //quicksort sorting
for (int l = 0; l < ct; ++l) {
printf("%d ", x[l]); //prints sorted array not necessary to question
}
cnt = count(x, ct); //counts the number of non-repeated vertices
printf("%d\n", cnt);
}
The problem was the bounds of the array int x[1000] is not enough for the data given below.

Find a hash function to malfunction insertion sort

Below is the original pseudocode for Insertion Sort:
function INSERTIONSORT(A[0..n−1])
for i←1 to n−1 do
j←i−1
while j≥0 and A[j+1]<A[j] do
SWAP(A[j+1],A[j])
j←j−1
A company is using Insertion Sort inside one of their products. You are a cybersecurity expert that was hired by this company to assess any security flaws with their code. After a few tries, you managed to attack their Insertion Sort code and modify it in the following way:
function INSERTIONSORT(A[0..n−1])
for i←1 to n−1 do
j←i−1
while j≥0 and HASH(A,j+1) < HASH(A,j) do
SWAP(A[j+1],A[j])
j←j−1
In other words, instead of indexing the array as A[j] and A[j+1]inside the “while” condition, you now have a hash function that takes the array and a index as the arguments and return an integer. Your job is to implement specific hash functions that will cause the algorithm to malfunction in different ways.
a) Implement a hash function that causes Insertion Sort to keep the original array unchanged. Explain why your solution works.
b) Implement a hash function that causes Insertion Sort to always run in the worst case complexity, even if the resulting array does not end up getting sorted. Explain why your solution works.
c) Implement a hash function that causes Insertion Sort to sort the array in reverse. Explain why your solution works.
I think (a) and (b) is hash(A,j)=j and hash(A,j)=-j, but have no idea if that is correct and have no clue to c.
**Part a) Original array unchanged
#include <stdio.h>
int hash(int arr[], int i) {
return i;
}
void insertionSort(int arr[], int n) {
int i, j, temp;
for (i = 1 ; i <= n - 1; i++)
{
j = i-1;
while ( j >= 0 && hash(arr, j+1) < hash(arr, j))
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
j--;
}
}
}
int main()
{
int i;
int arr[] = {5, 6, 7, 3, 2 , 9, 4};
int n = sizeof(arr)/sizeof(arr[0]);
insertionSort(arr, n);
printf("Original array unchanged:\n");
for (i = 0; i <= n - 1; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}
Part b) Worst Case insertion sort
#include <stdio.h>
int hash(int arr[], int i) {
return -i;
}
void insertionSort(int arr[], int n) {
int i, j, temp;
for (i = 1 ; i <= n - 1; i++)
{
j = i-1;
while ( j >= 0 && hash(arr, j+1) < hash(arr, j))
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
j--;
}
}
}
int main()
{
int i;
int arr[] = {5, 6, 7, 3, 2 , 9, 4};
int n = sizeof(arr)/sizeof(arr[0]);
insertionSort(arr, n);
printf("In worst case(number of swaps maximum)\n");
for (i = 0; i <= n - 1; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}
Part c) Sorted in reverse order.**
#include <stdio.h>
int hash(int arr[], int i) {
return -arr[i];
}
void insertionSort(int arr[], int n) {
int i, j, temp;
for (i = 1 ; i <= n - 1; i++)
{
j = i-1;
while ( j >= 0 && hash(arr, j+1) < hash(arr, j))
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
j--;
}
}
}
int main()
{
int i;
int arr[] = {5, 6, 7, 3, 2 , 9, 4};
int n = sizeof(arr)/sizeof(arr[0]);
insertionSort(arr, n);
printf("Sorted in reverse order:\n");
for (i = 0; i <= n - 1; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}

What's the correct code for this pseudocode

I'm not quite getting pseudocode FOR loop thing.
What would be the correct code (in any language) for this pseudocode?
function myFunction(arr[])
for i = 0 to length(arr)
if (arr[i] > i) then
j = i
while (j < length(arr)) and (arr[j] >= j)
j = j + 1
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
i = 0
Here it is, in C# (or Java, if you decapitalize "Length"):
void myFunction(int[] arr)
{
for(int i = 0; i < arr.Length; i++)
{
if(arr[i] > i)
{
int j = i;
while(j < arr.Length && arr[j] >= j)
j = j + 1;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i = 0;
}
}
}
Using while instead of for:
void myFunction(int[] arr)
{
int i = 0;
while(i < arr.Length)
{
if(arr[i] > i)
{
int j = i;
while(j < arr.Length && arr[j] >= j)
j = j + 1;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i = 0;
}
i++;
}
}
Note the indentation structure of the pseudocode:
function myFunction(arr[])
for i = 0 to length(arr)
if (arr[i] > i) then
...
This means that everything underneath the for declaration is inside the loop, and everything underneath the if, including setting i to 0, will be inside the conditional block. Given this fact, it must be the case that i will start again at 1 if the if statement is entered. What would happen if the code were as below?
void myFunction(int[] arr)
{
int i = 0;
while(i < arr.Length)
{
if(arr[i] > i)
{
int j = i;
while(j < arr.Length && arr[j] >= j)
j = j + 1;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
i = 0;
}
}
}
In the case arr[i] <= i, the loop never terminates.
You should always assume the last operation of an iterative loop is the shifting of the index, unless explicitly stated otherwise. This is how a for loop must behave, and how a while implementation ought to (by convention).
The code itself looks to be an attempt at a bubble sort implementation, but is sorting based on comparison against the index, rather than the other elements. I am not sure what it is meant to achieve.

Resources