I'm curious to know has my implementation of non recursive QuickSort algorithm some drawbacks or hidden rocks. What should be modified in order to optimize it? And what problems could happen when comparing two objects in the way I do it?
public class QuickSort <T extends Number> {
private Integer first, last, boundLo, boundHi, pivot;
Integer temp[] = {0, 0};
public void sort(NewArrayList<T> vect) {
Deque<Integer[]> stack = new ArrayDeque<Integer[]>();
first = 0;
last = vect.size() - 1;
stack.push(new Integer[] {first, last});
while(!stack.isEmpty()) {
sortStep(vect, stack);
}
}
private void sortStep(NewArrayList<T> vect, Deque<Integer[]> stack) {
// initialize indices
temp = stack.pop();
first = temp[0];
last = temp[1];
boundLo = first;
boundHi = last;
pivot = last;
while(first < last) {
if(vect.get(first).doubleValue() >= vect.get(pivot).doubleValue()) {
last--;
if(first != last)
vect.swap(first, last);
vect.swap(last, pivot);
pivot--;
}
else first++;
}
if(boundLo < (pivot - 1))
stack.add(new Integer[] {boundLo, pivot - 1});
if(boundHi > (pivot + 1))
stack.add(new Integer[] {pivot + 1, boundHi});
}
}
And is ArrayList the best collection for this kind of sort?
public class NewArrayList<T> extends ArrayList<T> {
public NewArrayList() {
super();
}
public void swap(int index1, int index2) {
this.set(index1, this.set(index2, this.get(index1)));
}
}
The code after modifying in consideration of the suggestions
public class QuickSort <T extends Number> {
private int first, last, boundLo, boundHi, pivot;
int temp[] = {0, 0};
public QuickSort() {
super();
}
public void sort(List<T> list) {
Deque<int[]> stack = new ArrayDeque<int[]>();
first = 0;
last = list.size() - 1;
stack.push(new int[] {first, last});
while(!stack.isEmpty()) {
sortStep(list, stack);
}
}
private void sortStep(List<T> list, Deque<int[]> stack) {
temp = stack.pop();
first = temp[0];
last = temp[1];
boundLo = first;
boundHi = last;
pivot = last;
while(first < last) {
if(list.get(first).doubleValue() >= list.get(pivot).doubleValue()) {
last--;
if(first != last)
Collections.swap(list, first, last);
Collections.swap(list, last, pivot);
pivot--;
}
else first++;
}
if(boundLo < (pivot - 1))
stack.add(new int[] {boundLo, pivot - 1});
if(boundHi > (pivot + 1))
stack.add(new int[] {pivot + 1, boundHi});
}
}
public class Sort {
/** Returns a sorted list of attributes. */
protected int[] sortAttributes1(int[] array) {
Queue<Range> queue = new ArrayDeque<Range>();
while (!queue.isEmpty()) {
Range range = queue.poll();
if (range.isEmpty()) {
continue;
}
int left = range.getLeft();
int right = range.getRight();
// partition the range
right = partition(array, left, right);
Range lr = new Range(range.getLeft(), right - 1);
Range rr = new Range(right + 1, range.getRight());
queue.add(lr);
queue.add(rr);
}
return array;
}
private int partition(int[] array, int left, int right) {
int pivot = right - left >>> 2;
while (left <= right) {
int pivotVal = array[pivot];
if (array[left] <= pivotVal) {
left++;
continue;
}
right--;
if (left == right)continue;
int temp = array[left];
array[left] = array[right];
array[right] = temp;
}
int temp = array[pivot];
array[pivot] = array[right];
array[right] = temp;
return right;
}
}
Related
I'm trying to implement a heapsort on an array of objects which has already been created. It is meant to be sorted according to their eventTime attribute, yet each eventTime attribute is set to the same as the others by the time the queue is sorted. Is there any way to fix this so that it creates a 'priorityqueue' in ascending order?
Main:
public static void main(String[] args) {
CustomerQueue cQ = new CustomerQueue(0, 0, false);
for (int i = 0; i < 10; i++) {
CustomerQueue cQ1 = new CustomerQueue(0, 0, false);
cQ.enqueue(cQ1);
System.out.println(cQ1.arrivalTime);
}
System.out.print("\n");
PriorityQueue pQ = new PriorityQueue(0, 0, 0, false);
while (!cQ.isEmpty()) {
for (CustomerQueue c : cQ.array) {
PriorityQueue pQ1 = new PriorityQueue(0, 0, 0, false);
pQ1.eventTime = c.arrivalTime;
pQ.enqueue(pQ1);
System.out.println(pQ1.eventTime);
cQ.dequeue();
}
}
pQ.sort(pQ.array);
System.out.println(Arrays.toString(pQ.array));
}
PriorityQueue:
class PriorityQueue {
PriorityQueue array[] = new PriorityQueue[10];
private int front;
private int rear;
private int count;
private int eventType;
double eventTime;
private double tallyTime;
private boolean paymentMethod;
public PriorityQueue(int evT, int eT, double tT, boolean pM) {
this.eventType = evT;
this.eventTime = eT;
this.tallyTime = tT;
this.paymentMethod = pM;
front = 0;
rear = -1;
count = 0;
}
public void enqueue(PriorityQueue pQ) {
if (isFull()) {
System.out.println("OverFlow\nProgram Terminated");
System.exit(1);
}
rear = (rear + 1);
array[rear] = pQ;
count++;
}
public void sort(PriorityQueue arr[]) {
int n = arr.length;
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// One by one extract an element from heap
for (int i = n - 1; i >= 0; i--) {
// Move current root to end
int temp = (int) arr[0].eventTime;
arr[0] = arr[i];
arr[i].eventTime = temp;
// call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
void heapify(PriorityQueue arr[], int n, int i) {
int largest = i; // Initialize largest as root
int l = 2 * i + 1; // left = 2*i + 1
int r = 2 * i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l].eventTime > arr[largest].eventTime) {
largest = l;
}
// If right child is larger than largest so far
if (r < n && arr[r].eventTime > arr[largest].eventTime) {
largest = r;
}
// If largest is not root
if (largest != i) {
int swap = (int) arr[i].eventTime;
arr[i] = arr[largest];
arr[largest].eventTime = swap;
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
public void dequeue() {
if (isEmpty()) {
System.out.println("UnderFlow\nProgram Terminated");
System.exit(1);
}
front = (front + 1) % array.length;
count--;
}
public boolean isEmpty() {
return (size() == 0);
}
public int size() {
return count;
}
public boolean isFull() {
return (size() == array.length);
}
public PriorityQueue peek() {
if (isEmpty()) {
System.out.println("UnderFlow\nProgram Terminated");
System.exit(1);
}
return array[front];
}
#Override
public String toString() {
return eventType + " " + eventTime + " " + tallyTime + " " + paymentMethod;
}
}
I see two parts which are most likely wrong and the cause of your issue:
In the heapify method you have:
int swap = (int) arr[i].eventTime;
arr[i] = arr[largest];
arr[largest].eventTime = swap;
And in the sort method you have:
int temp = (int) arr[0].eventTime;
arr[0] = arr[i];
arr[i].eventTime = temp;
Assuming you want to switch the CustomerQueue objects around inside the array, they should be this instead:
// In the heapify:
CustomerQueue swap = arr[i];
arr[i] = arr[largest];
arr[largest] = swap;
// In the sort:
CustomerQueue temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
What your code currently does in pseudo-code is this:
CustomerQueue ith has for example name = "I", eventTime = 1
CustomerQueue largest has for example name = "largest", eventTime = 2
int temp = (int) arr[i].eventTime; // temp is now 1
arr[i] = arr[largest]; // Both arr[i] AND arr[largest] are now CustomerQueue largest (with name = "largest" and eventTime = 2)
arr[i].eventTime = temp; // Both arr[i] AND arr[largest] are now changed to eventTime temp (which is 1)
So now both arr[i] and arr[largest] will hold: name = "largest" and eventTime = 1, as well as referencing the same CustomerQueue-instance.
Why is this code not working ?
The following is a recursive approach to quicksort.
Can somebody also suggest a better partitioning algorithm with pivot take as first element ?
import java.util.*;
class QuickSort
{
public static void callQuickSort(int[] array,int left,int right)
{
if(left<right)
{
int s = partition(array,left,right);
callQuickSort(array,left,s-1);
callQuickSort(array,s+1,right);
}
}
public static int partition(int[] array,int left,int right)
{
int pI = left; //pI = partition index
int pivot = array[right];
for(int i=left;i<=right-1;i++)
{
if(array[i] <= pivot)
{
swap(array[i],array[pI]);
pI++;
}
}
swap(array[pI],array[right]);
return pI;
}
static void swap(int a,int b)
{
int temp = a;
a = b;
b = temp;
}
public static void main(String args[])
{
int[] array = {7,2,1,6,8,5,3,4};//array declared
callQuickSort(array,0,7);
System.out.println("Sorted array is - ");
for(int i=0;i<8;i++)
System.out.print(array[i]+"\t");
}
}//end of class
The output is
7 2 1 6 8 5 3 4
The above code returns the array without any change. Why isn't the array changing ?
In java data is passed in method by value, not by reference, so you can't use swap method as you do.
Here is working code:
class QuickSort {
public static void callQuickSort(int[] array, int left, int right) {
if (left < right) {
int s = partition(array, left, right);
callQuickSort(array, left, s - 1);
callQuickSort(array, s + 1, right);
}
}
public static int partition(int[] array, int left, int right) {
int pI = left; //pI = partition index
int pivot = array[right];
for (int i = left; i <= right - 1; i++) {
if (array[i] <= pivot) {
int temp = array[i];
array[i] = array[pI];
array[pI] = temp;
// swap(array[i], array[pI]);
pI++;
}
}
int temp = array[pI];
array[pI] = array[right];
array[right] = temp;
// swap(array[pI], array[right]);
return pI;
}
/*static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}*/
public static void main(String args[]) {
int[] array = {7, 2, 1, 6, 8, 5, 3, 4};//array declared
callQuickSort(array, 0, 7);
System.out.println("Sorted array is - ");
for (int i = 0; i < 8; i++)
System.out.print(array[i] + "\t");
}
}//end of class
Current I have a home work question which says,
It is possible to make the heap sort algorithm more efficient by
writing a method that will order the entire list at once instead of
adding the elements one at a time.
However I can't figure out what exactly it means by "instead of adding elements one at a time", surely one has to building a heap first (which involves adding element from a unsorted list one by one), then remove the largest from the heap one at a time.
Here is my heap array:
import exceptions.exceptions.*;
public class ArrayHeap<T> extends ArrayBinaryTree<T> implements HeapADT<T> {
public ArrayHeap(){
super();
}
public void addElement (T element){
if (count==size())
expandCapacity();
tree[count] = element;
count++;
if (count > 1)
heapifyAdd();
}
private void heapifyAdd(){
int index = count - 1;
while ((index != 0) && (((Comparable)tree[index]).compareTo(tree[(index-1)/2]) < 0))
{
T temp = tree[index];
tree[index] = tree[(index-1)/2];
tree[(index-1)/2] = temp;
index = (index-1)/2;
}
}
public T removeMin(){
if (isEmpty())
throw new EmptyCollectionException ("Empty Heap");
T minElement = findMin();
tree[0] = tree[count-1];
heapifyRemove();
count--;
return minElement;
}
private void heapifyRemove()
{
T temp;
int node = 0;
int left = 1;
int right = 2;
int next;
if ((tree[left] == null) && (tree[right] == null))
next = count;
else if (tree[left] == null)
next = right;
else if (tree[right] == null)
next = left;
else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
next = left;
else
next = right;
while ((next < count) && (((Comparable)tree[next]).compareTo(tree[node]) < 0)){
temp = tree[node];
tree[node] = tree[next];
tree[next] = temp;
node = next;
left = 2*node + 1;
right = 2*(node+1);
if ((tree[left] == null) && (tree[right] == null))
next = count;
else if (tree[left] == null)
next = right;
else if (tree[right] == null)
next = left;
else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
next = left;
else
next = right;
}
}
public T findMin() {
if (isEmpty())
throw new EmptyCollectionException ("Empty Heap");
return tree[0];
}
}
Here is more HeapSort algorithm:
import ArrayHeap;
public class HeapSort<T>{
public T[] heapsort(T[] data, int min, int max){
ArrayHeap<T> temp = new ArrayHeap<T>();
for (int c = min; c <= max; c++){
temp.addElement(data[c]);
}
int count = min;
while(!(temp.isEmpty())){
T jj = temp.removeMin();
data[count] = jj;
count ++;
}
return data;
}
The most straight-forward way to perform heapsort is to use a separate heap and add all the elements to it, then the elements will be in order when we pop them out one by one. This is what "adding the elements one at a time" refers to in the statement, and this is what your implementation is doing: create a heap of type ArrayHeap and insert the elements of data to it, in the end pop the elements back to data.
A more efficient way (in terms of both space and time) is to perform in-place sorting, where we use the array to be sorted as the heap, rather than using additional memory for the heap, this is what "order the entire list at once" refers to. The steps of this implementation is as follow, we will order the elements in non-decreasing order:
We max-heapify the input array (i.e. we re-arrange the elements in the array so that it follows the max-heap property.
For i = n - 1 to 1:
Swap the 0-th element in the array with the i-th element.
Decrease the size of the heap by 1 (i.e. the heap should be of size i).
Perform the sift-down operation on the heap to restore the max-heap property.
Note that whenever the max-heap property holds, the top-most element in the heap is the largest element, so at the start of the k-th iteration (k = n - i here) the 0-th element is the k-largest element, and we place is in the correct position in the array by swapping.
Note that step 1 can be done in O(n), and in step 2 there are O(n) iterations and each sift-down operation takes time O(log(n)), so the overall time complexity is O(n log(n)).
Below is an implementation in Java for your reference:
import java.util.Random;
public class HeapSort {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.println(String.format("Iteration number %d%n", i));
Integer[] array = randomIntArray(10, 0, 100);
System.out.println(String.format("Array before sorting: [%s]", toStr(array)));
heapSort(array);
System.out.println(String.format("Array after sorting: [%s]", toStr(array)));
System.out.println("================================================================");
}
}
private static <T extends Comparable<T>> T[] heapSort(T[] array) {
maxHeapify(array, array.length);
for (int i = array.length - 1; i > 0; i--) {
swap(array, 0, i);
siftDown(array, i, 0);
}
return array;
}
private static <T extends Comparable<T>> void maxHeapify(T[] array, int heapSize) {
for (int i = getParentIdx(heapSize - 1); i >= 0; i--) {
siftDown(array, heapSize, i);
}
}
private static <T extends Comparable<T>> void siftDown(T[] array, int heapSize, int idx) {
final int length = Math.min(array.length, heapSize) - 1;
if (idx > length || idx < 0) throw new IllegalArgumentException("Index out of range");
while (true) {
int maxIdx = idx;
int leftChildIdx = getLeftChildIdx(idx);
int rightChildIdx = getRightChildIdx(idx);
if (leftChildIdx <= length && array[maxIdx].compareTo(array[leftChildIdx]) < 0) maxIdx = leftChildIdx;
if (rightChildIdx <= length && array[maxIdx].compareTo(array[rightChildIdx]) < 0) maxIdx = rightChildIdx;
if (idx != maxIdx) {
swap(array, idx, maxIdx);
idx = maxIdx;
} else {
return;
}
}
}
private static int getParentIdx(int idx) {
return (idx - 1) / 2;
}
private static int getLeftChildIdx(int idx) {
return idx * 2 + 1;
}
private static int getRightChildIdx(int idx) {
return idx * 2 + 2;
}
private static <T> void swap(T[] array, int i, int j) {
T tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
private static <T> String toStr(T[] array) {
StringBuilder sb = new StringBuilder();
for (T element : array) {
sb.append(element + ", ");
}
return sb.substring(0, sb.length() - 2);
}
private static Integer[] randomIntArray(int size, int lowerBound, int upperBound) {
Integer[] result = new Integer[size];
Random random = new Random();
int diff = upperBound - lowerBound + 1;
for (int i = 0; i < size; i++) result[i] = lowerBound + random.nextInt(diff);
return result;
}
}
I try to use "randomized pivot" method to find the Kth min elem among given array.
[The code]
public class FindKthMin {
// Find the Kth min elem by randomized pivot.
private static void exchange (int[] givenArray, int firstIndex, int secondIndex) {
int tempElem = givenArray[firstIndex];
givenArray[firstIndex] = givenArray[secondIndex];
givenArray[secondIndex] = tempElem;
}
private static int partition (int[] givenArray, int start, int end, int pivotIndex) {
// Debug:
//System.out.println("debug: start = " + start);
//System.out.println(">> end = " + end);
//System.out.println(">> pivotIndex = " + pivotIndex);
int pivot = givenArray[pivotIndex];
int left = start - 1;
int right = end;
boolean hasDone = false;
while (!hasDone) {
while (!hasDone) {
left ++;
if (left == right) {
hasDone = true;
break;
}
if (givenArray[left] >= pivot) {
// Exchange givenArray[left] and the givenArray[right].
exchange(givenArray, left, right);
break;
}
}
while (!hasDone) {
right --;
if (left == right) {
hasDone = true;
break;
}
if (givenArray[right] < pivot) {
// Exchange the givenArray[right] and the givenArray[left].
exchange(givenArray, right, left);
break;
}
}
}
givenArray[right] = pivot;
// Debug:
//System.out.println(">> split = " + right);
//System.out.println();
return right;
}
private static int findKthMin_RanP_Helper (int[] givenArray, int start, int end, int k) {
if (start > end) return -1;
// Generate a random num in the range[start, end].
int rand = (int)(start + Math.random() * (end - start + 1));
// Using this random num as the pivot index to partition the array in the current scope.
int split = partition(givenArray, start, end, rand);
if (k == split + 1) return givenArray[split];
else if (k < split + 1) return findKthMin_RanP_Helper(givenArray, start, split - 1, k);
else return findKthMin_RanP_Helper(givenArray, split + 1, end, k);
}
public static int findKthMin_RanP (int[] givenArray, int k) {
int size = givenArray.length;
if (k < 1 || k > size) return -1;
return findKthMin_RanP_Helper(givenArray, 0, size - 1, k);
}
// Main method to test.
public static void main (String[] args) {
// Test data: {8, 9, 5, 2, 8, 4}.
int[] givenArray = {8, 9, 5, 2, 8, 4};
// Test finding the Kth min elem by randomized pivot method.
System.out.println("Test finding the Kth min elem by randomized pivot method, rest = " + findKthMin_RanP(givenArray, 1));
}
}
But the result is unstable, sometimes right and sometimes wrong.
Please have a look at the 5th row of findKthMin_RanP_Helper method:
If I change this int split = partition(givenArray, start, end, rand); to int split = partition(givenArray, start, end, end);, the result is always correct. I really can not find what's wrong with this.
EDIT:
The problem comes from the "partition", the new partition should like this:
private static int partition_second_version (int[] givenArray, int start, int end, int pivotIndex) {
int pivot = givenArray[pivotIndex];
int left = start;
int right = end;
while (left <= right) {
while (givenArray[left] < pivot) left ++;
while (givenArray[right] > pivot) right --;
if (left <= right) {
// Exchange givenArray[left] and givenArray[right].
exchange(givenArray, left, right);
left ++;
right --;
}
}
return left;
}
And the findKthMin_RanP_Helper should be changed like this:
private static int findKthMin_RanP_Helper (int[] givenArray, int start, int end, int k) {
if (start > end) return -1;
// Generate a random num in the range[start, end].
int rand = start + (int)(Math.random() * ((end - start) + 1));
// Using this random num as the pivot index to partition the array in the current scope.
int split = partition_second_version (givenArray, start, end, rand);
if (k == split) return givenArray[split - 1];
else if (k < split) return findKthMin_RanP_Helper(givenArray, start, split - 1, k);
else return findKthMin_RanP_Helper(givenArray, split, end, k);
}
Your partition routine could be simplified...
private static int partition(int[] givenArray, int start, int end, int pivotIndex) {
final int pivot = givenArray[pivotIndex];
int left = start;
int right = end;
while (left < right) {
while (left < givenArray.length && givenArray[left] <= pivot) {
left++;
}
while (right > -1 && givenArray[right] > pivot) {
right--;
}
if (left >= right) {
break;
}
exchange(givenArray, right, left);
}
return right;
}
The one bug I see in your code is your partition routine. In the first exchange call, it is not guaranteed that the right index will always point to a value which is < pivot.
I am trying to make a merge sort method, but it keeps on giving the wrong sorts. Where do I have change to make it actually sort the array? What part of the code has to be different? Thank you for your time.
public static void mergeSort(int[] array, int left, int lHigh, int right, int rHigh) {
int elements = (rHigh - lHigh +1) ;
int[] temp = new int[elements];
int num = left;
while ((left <= lHigh) && (right <= rHigh)){
if (a[left] <= array[right]) {
temp[num] = array[left];
left++;
}
else {
temp[num] = array[right];
right++;
}
num++;
}
while (left <= right){
temp[num] = array[left]; // I'm getting an exception here, and is it because of the num???
left += 1;
num += 1;
}
while (right <= rHigh) {
temp[num] = array[right];
right += 1;
num += 1;
}
for (int i=0; i < elements; i++){
array[rHigh] = temp[rHigh];
rHigh -= 1;
}
EDIT: now the mergeSort doesn't really sort the numbers, can someone tell me where it specifically is? especially when I print the "Testing merge sort" part.
First of all, I'm assuming this is academic rather than practical, since you're not using a built in sort function. That being said, here's some help to get you moving in the right direction:
Usually, one can think of a merge sort as two different methods: a merge() function that merges two sorted lists into one sorted list, and mergeSort() which recursively breaks the list into single element lists. Since a single element list is sorted already, you then merge all the lists together into one big sorted list.
Here's some off-hand pseudo-code:
merge(A, B):
C = empty list
While A and B are not empty:
If the first element of A is smaller than the first element of B:
Remove first element of A.
Add it to the end of C.
Otherwise:
Remove first element of B.
Add it to the end of C.
If A or B still contains elements, add them to the end of C.
mergeSort(A):
if length of A is 1:
return A
Split A into two lists, L and R.
Q = merge(mergeSort(L), mergeSort(R))
return Q
Maybe that'll help clear up where you want to go.
If not, there's always MergeSort at wikipedia.
Additional:
To help you out, here are some comments inline in your code.
public static void mergeSort(int[] array, int left, int lHigh, int right, int rHigh) {
// what do lHigh and rHigh represent?
int elements = (rHigh - lHigh +1) ;
int[] temp = new int[elements];
int num = left;
// what does this while loop do **conceptually**?
while ((left <= lHigh) && (right <= rHigh)){
if (a[left] <= a[right]) {
// where is 'pos' declared or defined?
temp[pos] = a[left];
// where is leftLow declared or defined? Did you mean 'left' instead?
leftLow ++;
}
else {
temp[num] = a[right];
right ++;
}
num++;
}
// what does this while loop do **conceptually**?
while (left <= right){
// At this point, what is the value of 'num'?
temp[num] = a[left];
left += 1;
num += 1;
}
while (right <= rHigh) {
temp[num] = a[right];
right += 1;
num += 1;
}
// Maybe you meant a[i] = temp[i]?
for (int i=0; i < elements; i++){
// what happens if rHigh is less than elements at this point? Could
// rHigh ever become negative? This would be a runtime error if it did
a[rHigh] = temp[rHigh];
rHigh -= 1;
}
I'm purposefully being vague so you think about the algorithm. Try inserting your own comments into the code. If you can write what is conceptually happening, then you may not need Stack Overflow :)
My thoughts here are that you are not implementing this correctly. This is because it looks like you're only touching the elements of the array only once (or close to only once). This means you have a worst case scenario of O(N) Sorting generally takes at least O(N * log N) and from what I know, the simpler versions of merge sort are actually O(N^2).
More:
In the most simplistic implementation of merge sort, I would expect to see some sort of recursion in the mergeSort() method. This is because merge sort is generally defined recursively. There are ways to do this iteratively using for and while loops, but I definitely don't recommend it as a learning tool until you get it recursively.
Honestly, I suggest taking either my pseudo-code or the pseudo-code you may find in a wikipedia article to implement this and start over with your code. If you do that and it doesn't work correctly still, post it here and we'll help you work out the kinks.
Cheers!
And finally:
// Precondition: array[left..lHigh] is sorted and array[right...rHigh] is sorted.
// Postcondition: array[left..rHigh] contains the same elements of the above parts, sorted.
public static void mergeSort(int[] array, int left, int lHigh, int right, int rHigh) {
// temp[] needs to be as large as the number of elements you're sorting (not half!)
//int elements = (rHigh - lHigh +1) ;
int elements = rHigh - left;
int[] temp = new int[elements];
// this is your index into the temp array
int num = left;
// now you need to create indices into your two lists
int iL = left;
int iR = right;
// Pseudo code... when you code this, make use of iR, iL, and num!
while( temp is not full ) {
if( left side is all used up ) {
copy rest of right side in.
make sure that at the end of this temp is full so the
while loop quits.
}
else if ( right side is all used up) {
copy rest of left side in.
make sure that at the end of this temp is full so the
while loop quits.
}
else if (array[iL] < array[iR]) { ... }
else if (array[iL] >= array[iR]) { ... }
}
}
public class MergeSort {
public static void main(String[] args) {
int[] arr = {5, 4, 7, 2, 3, 1, 6, 2};
print(arr);
new MergeSort().sort(arr, 0, arr.length - 1);
}
private void sort(int[] arr, int lo, int hi) {
if (lo < hi) {
int mid = (lo + hi) / 2;
sort(arr, lo, mid); // recursive call to divide the sub-list
sort(arr, mid + 1, hi); // recursive call to divide the sub-list
merge(arr, lo, mid, hi); // merge the sorted sub-lists.
print(arr);
}
}
private void merge(int[] arr, int lo, int mid, int hi) {
// allocate enough space so that the extra 'sentinel' value
// can be added. Each of the 'left' and 'right' sub-lists are pre-sorted.
// This function only merges them into a sorted list.
int[] left = new int[(mid - lo) + 2];
int[] right = new int[hi - mid + 1];
// create the left and right sub-list for merging into original list.
System.arraycopy(arr, lo, left, 0, left.length - 1);
System.arraycopy(arr, mid + 1, right, 0, left.length - 1);
// giving a sentinal value to marking the end of the sub-list.
// Note: The list to be sorted is assumed to contain numbers less than 100.
left[left.length - 1] = 100;
right[right.length - 1] = 100;
int i = 0;
int j = 0;
// loop to merge the sorted sequence from the 2 sub-lists(left and right)
// into the main list.
for (; lo <= hi; lo++) {
if (left[i] <= right[j]) {
arr[lo] = left[i];
i++;
} else {
arr[lo] = right[j];
j++;
}
}
}
// print the array to console.
private static void print(int[] arr) {
System.out.println();
for (int i : arr) {
System.out.print(i + ", ");
}
}
}
Here's another!
private static int[] mergeSort(int[] input){
if (input.length == 1)
return input;
int length = input.length/2;
int[] left = new int[length];
int[] right = new int[input.length - length];
for (int i = 0; i < length; i++)
left[i] = input[i];
for (int i = length; i < input.length; i++)
right[i-length] = input[i];
return merge(mergeSort(left),mergeSort(right));
}
private static int[] merge(int[] left, int[] right){
int[] merged = new int[left.length+right.length];
int lengthLeft = left.length;
int lengthRight = right.length;
while (lengthLeft > 0 && lengthRight > 0){
if (left[left.length - lengthLeft] < right[right.length - lengthRight]){
merged[merged.length -lengthLeft-lengthRight] = left[left.length - lengthLeft];
lengthLeft--;
}else{
merged[merged.length - lengthLeft-lengthRight] = right[right.length - lengthRight];
lengthRight--;
}
}
while (lengthLeft > 0){
merged[merged.length - lengthLeft] = left[left.length-lengthLeft];
lengthLeft--;
}
while (lengthRight > 0){
merged[merged.length - lengthRight] = right[right.length-lengthRight];
lengthRight--;
}
return merged;
}
static void mergeSort(int arr[],int p, int r) {
if(p<r) {
System.out.println("Pass "+k++);
int q = (p+r)/2;
mergeSort(arr,p,q);
mergeSort(arr,q+1,r);
//System.out.println(p+" "+q+" "+r);
merge(arr,p,q,r);
}
}
static void merge(int arr[],int p,int q,int r) {
int temp1[],temp2[];
//lower limit array
temp1 = new int[q-p+1];
//upper limit array
temp2 = new int[r-q];
for(int i=0 ; i< (q-p+1); i++){
temp1[i] = arr[p+i];
}
for(int j=0; j< (r-q); j++){
temp2[j] = arr[q+j+1];
}
int i = 0,j=0;
for(int k=p;k<=r;k++){
// This logic eliminates the so called sentinel card logic mentioned in Coreman
if(i!= temp1.length
&& (j==temp2.length || temp1[i] < temp2[j])
) {
arr[k] = temp1[i];
// System.out.println(temp1[i]);
i++;
}
else {
//System.out.println(temp2[j]);
arr[k] = temp2[j];
j++;
}
}
}
>
Merge Sort Using Sentinel
This codes works perfectly fine.
public void mergeSort(int a[], int low, int high) {
if (low < high) {
int mid = (low + high) / 2;
mergeSort(a, low, mid);
mergeSort(a, mid + 1, high);
merge(a, low, mid, high);
}
}
public void merge(int a[], int low, int mid, int high) {
int n1 = mid - low + 1;// length of an array a1
int n2 = high - mid; // length of an array a2
int a1[] = new int[n1 + 1];
int a2[] = new int[n2 + 1];
int lowRange = low;
for (int i = 0; i < n1; i++) {
a1[i] = a[lowRange];
lowRange++;
}
for (int j = 0; j < n2; j++) {
a2[j] = a[mid + j + 1];
}
a1[n1] = Integer.MAX_VALUE; // inserting sentinel at the end of array a1
a2[n2] = Integer.MAX_VALUE; // inserting sentinel at the end of array a2
int i = 0;
int j = 0;
int k = low;
for (k = low; k <= high; k++) {
if (a1[i] >= a2[j]) {
a[k] = a2[j];
j++;
} else {
a[k] = a1[i];
i++;
}
}
if (a2.length >= a1.length) {
for (int ab = k; ab < a2.length; ab++) {
a[k] = a2[ab];
k++;
}
} else if (a1.length >= a2.length) {
for (int ab = k; ab < a1.length; ab++) {
a[k] = a1[ab];
k++;
}
}
}
Here's another alternative:
public class MergeSort {
public static void merge(int[]a,int[] aux, int f, int m, int l) {
for (int k = f; k <= l; k++) {
aux[k] = a[k];
}
int i = f, j = m+1;
for (int k = f; k <= l; k++) {
if(i>m) a[k]=aux[j++];
else if (j>l) a[k]=aux[i++];
else if(aux[j] > aux[i]) a[k]=aux[j++];
else a[k]=aux[i++];
}
}
public static void sort(int[]a,int[] aux, int f, int l) {
if (l<=f) return;
int m = f + (l-f)/2;
sort(a, aux, f, m);
sort(a, aux, m+1, l);
merge(a, aux, f, m, l);
}
public static int[] sort(int[]a) {
int[] aux = new int[a.length];
sort(a, aux, 0, a.length-1);
return a;
}
}
Here is a simple merge sort algorithm in Java:
Good Tip: Always use int middle = low + (high-low)/2 instead of int middle = (low + high)/2.
public static int[] mergesort(int[] arr) {
int lowindex = 0;
int highindex = arr.length-1;
mergesort(arr, lowindex, highindex);
return arr;
}
private static void mergesort(int[] arr, int low, int high) {
if (low == high) {
return;
} else {
int midIndex = low + (high-low)/2;
mergesort(arr, low, midIndex);
mergesort(arr, midIndex + 1, high);
merge(arr, low, midIndex, high);
}
}
private static void merge(int[] arr, int low, int mid, int high) {
int[] left = new int[mid-low+2];
for (int i = low; i <= mid; i++) {
left[i-low] = arr[i];
}
left[mid-low+1] = Integer.MAX_VALUE;
int[] right = new int[high-mid+1];
for (int i = mid+1; i <= high; i++) {
right[i-mid-1] = arr[i];
}
right[high - mid] = Integer.MAX_VALUE;
int i = 0;
int j = 0;
for (int k = low; k <= high; k++) {
if (left[i] <= right[j]) {
arr[k] = left[i];
i++;
} else {
arr[k] = right[j];
j++;
}
}
}
package com.sortalgo;
import java.util.Arrays;
public class MyMSort {
private static void merge(int[] array, int[] result, int low, int mid, int high) {
int k =low, i=low; int j=mid+1;
while(i<=mid && j<=high) {
if(array[i]<= array[j]) {
result[k++]=array[i++];
}else {
result[k++]=array[j++];
}
}
while(i<=mid) {
result[k++]=array[i++];
}
while(j<=high) {
result[k++]=array[j++];
}
for(i=low;i<=high;i++) {
array[i]=result[i];
}
}
private static void mergeSort(int[] array, int[] result, int low, int high) {
if(high == low) {
return ;
}
int mid = (low + high)/2;
mergeSort(array,result, low, mid );
mergeSort(array,result, mid+1, high );
merge(array, result, low, mid, high);
}
public static void main(String[] args) {
int[] array = {8,4,3,12,25,6,13,10};
int[] result = new int[array.length];
mergeSort(array, result, 0, array.length-1 );
for(int i=0; i<=array.length-1;i++) {
System.out.println(array[i]);
}
}
}