Merge sort on linkedlist
http://javabypatel.blogspot.in/2015/12/merge-sort-linked-list.html
private
Node mergeSortLinkList(Node startNode){
if
(startNode==
null
|| startNode.getNext()==
null
){
return
startNode;
}
Node middle = getMiddle(startNode);
Node nextOfMiddle = middle.getNext();
middle.setNext(
null
);
Node left = mergeSortLinkList(startNode);
Node right = mergeSortLinkList(nextOfMiddle);
Node sortedList = mergeTwoListRecursive(left, right);
return
sortedList;
}
private
Node mergeTwoListRecursive(Node leftStart, Node rightStart){
if
(leftStart==
null
)
return
rightStart;
if
(rightStart==
null
)
return
leftStart;
Node temp=
null
;
if
(leftStart.getData()<rightStart.getData()){
temp=leftStart;
temp.setNext(mergeTwoListRecursive(leftStart.getNext(), rightStart));
}
else
{
temp=rightStart;
temp.setNext(mergeTwoListRecursive(leftStart, rightStart.getNext()));
}
return
temp;
}
private
Node getMiddle(Node startNode) {
if
(startNode==
null
){
return
startNode;
}
Node pointer1=startNode;
Node pointer2=startNode;
while
(pointer2!=
null
&& pointer2.getNext()!=
null
&& pointer2.getNext().getNext()!=
null
){
pointer1 = pointer1.getNext();
pointer2 = pointer2.getNext().getNext();
}
return
pointer1;
}
private
Node mergeTwoListIterative(Node leftStart, Node rightStart) {
Node merged=
null
;
Node temp=
null
;
Node lastAddedNode =
null
;
while
(leftStart!=
null
&& rightStart!=
null
){
if
(leftStart.getData()>rightStart.getData()){
temp =
new
Node(rightStart.getData());
rightStart=rightStart.getNext();
}
else
{
temp =
new
Node(leftStart.getData());
leftStart=leftStart.getNext();
}
if
(merged==
null
){
merged=temp;
}
else
{
lastAddedNode.setNext(temp);
}
lastAddedNode=temp;
}
if
(leftStart!=
null
){
lastAddedNode.setNext(leftStart);
}
else
{
lastAddedNode.setNext(rightStart);
}
return
merged;
}
https://www.cs.cmu.edu/~adamchik/15-121/lectures/Sorting%20Algorithms/code/MergeSort.java
public static void mergeSort(Comparable [ ] a)
{
Comparable[] tmp = new Comparable[a.length];
mergeSort(a, tmp, 0, a.length - 1);
}
private static void mergeSort(Comparable [ ] a, Comparable [ ] tmp, int left, int right)
{
if( left < right )
{
int center = (left + right) / 2;
mergeSort(a, tmp, left, center);
mergeSort(a, tmp, center + 1, right);
merge(a, tmp, left, center + 1, right);
}
}
private static void merge(Comparable[ ] a, Comparable[ ] tmp, int left, int right, int rightEnd )
{
int leftEnd = right - 1;
int k = left;
int num = rightEnd - left + 1;
while(left <= leftEnd && right <= rightEnd)
if(a[left].compareTo(a[right]) <= 0)
tmp[k++] = a[left++];
else
tmp[k++] = a[right++];
while(left <= leftEnd)
tmp[k++] = a[left++];
while(right <= rightEnd)
tmp[k++] = a[right++];
for(int i = 0; i < num; i++, rightEnd--)
a[rightEnd] = tmp[rightEnd];
}
X.
http://www.vogella.com/tutorials/JavaAlgorithmsMergesort/article.html
http://www.java2novice.com/java-sorting-algorithms/merge-sort/
private int[] numbers;
private int[] helper;
private int number;
public void sort(int[] values) {
this.numbers = values;
number = values.length;
this.helper = new int[number];
mergesort(0, number - 1);
}
private void mergesort(int low, int high) {
if (low < high) {
int middle = low + (high - low) / 2;
mergesort(low, middle);
mergesort(middle + 1, high);
merge(low, middle, high);
}
}
private void merge(int low, int middle, int high) {
for (int i = low; i <= high; i++) {
helper[i] = numbers[i];
}
int i = low;
int j = middle + 1;
int k = low;
while (i <= middle && j <= high) {
if (helper[i] <= helper[j]) {
numbers[k] = helper[i];
i++;
} else {
numbers[k] = helper[j];
j++;
}
k++;
}
while (i <= middle) {
numbers[k] = helper[i];
k++;
i++;
}
}
X.
http://javahungry.blogspot.com/2013/06/java-sorting-program-code-merge-sort.html
public static int[] mergeSort(int [] list) {
if (list.length <= 1) {
return list;
}
// Split the array in half
int[] first = new int[list.length / 2];
int[] second = new int[list.length - first.length];
System.arraycopy(list, 0, first, 0, first.length);
System.arraycopy(list, first.length, second, 0, second.length);
// Sort each half
mergeSort(first);
mergeSort(second);
// Merge the halves together, overwriting the original array
merge(first, second, list);
return list;
}
private static void merge(int[] first, int[] second, int [] result) {
// Merge both halves into the result array
// Next element to consider in the first array
int iFirst = 0;
// Next element to consider in the second array
int iSecond = 0;
// Next open position in the result
int j = 0;
// As long as neither iFirst nor iSecond is past the end, move the
// smaller element into the result.
while (iFirst < first.length && iSecond < second.length) {
if (first[iFirst] < second[iSecond]) {
result[j] = first[iFirst];
iFirst++;
} else {
result[j] = second[iSecond];
iSecond++;
}
j++;
}
// copy what's left
System.arraycopy(first, iFirst, result, j, first.length - iFirst);
System.arraycopy(second, iSecond, result, j, second.length - iSecond);
}
It's stable.
http://www.vogella.com/tutorials/JavaAlgorithmsMergesort/article.html
public static void sort(Comparable[] a) {
Comparable[] aux = new Comparable[a.length];
sort(a, aux, 0, a.length-1);
assert isSorted(a);
}
http://www.sinbadsoft.com/blog/sorting-big-files-using-k-way-merge-sort/
It consists of two steps: first, split the file into small chunks that would fit in memory, load each chunk, sort it, and write it back on disk. Second, perform a k-way merge on all the sorted chunks to get the final result.
External Merge Sort
https://code.google.com/p/externalsortinginjava/source/browse/trunk/src/main/java/com/google/code/externalsorting/ExternalSort.java
http://exceptional-code.blogspot.com/2011/07/external-sorting-for-sorting-large.html
1. Start reading the input file from the beginning.
2. Read M (or less if number of entries remaining in the file is less than M) numbers from the file and store it into a temp buffer.
3. Sort (using any good sorting method - Quicksort, for example) the numbers in the buffer stored in step 2.
4. Create a temp file in disk and write out the sorted numbers from step 3 to this temp file. Save the name of the temp file.
5. Repeat step 2 to 4 until all numbers from the input file has been read, sorted, and written out to temp files.
6. Open all the temp files (and set the read pointer to the beginning of the files).
7. Find the minimum number from the set of numbers currently pointed to by the file read pointer.
8. Write the number to disk. (To increase efficiency you could write the number to a buffer first and then flush the buffer out to disk when the buffer is full. But modern I/O libraries should be doing this anyway for you).
9. Read another number from the file that contained the minimum number at step 7.
10. Repeat step 7 to 9 until all numbers from all the temp files have been processed, merged, and written out to disk
Mergesort using Fork/Join Framework
http://www.java-allandsundry.com/2012/08/mergesort-using-forkjoin-framework.html
http://www.oracle.com/technetwork/articles/java/fork-join-422606.html
https://github.com/cowtowncoder/java-merge-sort
http://www.geeksforgeeks.org/3-way-merge-sort/
public
static
void
mergeSort3Way(Integer[] gArray)
{
if
(gArray ==
null
)
return
;
Integer[] fArray =
new
Integer[gArray.length];
for
(
int
i =
0
; i < fArray.length; i++)
fArray[i] = gArray[i];
mergeSort3WayRec(fArray,
0
, gArray.length, gArray);
for
(
int
i =
0
; i < fArray.length; i++)
gArray[i] = fArray[i];
}
public
static
void
mergeSort3WayRec(Integer[] gArray,
int
low,
int
high, Integer[] destArray)
{
if
(high - low <
2
)
return
;
int
mid1 = low + ((high - low) /
3
);
int
mid2 = low +
2
* ((high - low) /
3
) +
1
;
mergeSort3WayRec(destArray, low, mid1, gArray);
mergeSort3WayRec(destArray, mid1, mid2, gArray);
mergeSort3WayRec(destArray, mid2, high, gArray);
merge(destArray, low, mid1, mid2, high, gArray);
}
public
static
void
merge(Integer[] gArray,
int
low,
int
mid1,
int
mid2,
int
high,
Integer[] destArray)
{
int
i = low, j = mid1, k = mid2, l = low;
while
((i < mid1) && (j < mid2) && (k < high))
{
if
(gArray[i].compareTo(gArray[j]) <
0
)
{
if
(gArray[i].compareTo(gArray[k]) <
0
)
destArray[l++] = gArray[i++];
else
destArray[l++] = gArray[k++];
}
else
{
if
(gArray[j].compareTo(gArray[k]) <
0
)
destArray[l++] = gArray[j++];
else
destArray[l++] = gArray[k++];
}
}
while
((i < mid1) && (j < mid2))
{
if
(gArray[i].compareTo(gArray[j]) <
0
)
destArray[l++] = gArray[i++];
else
destArray[l++] = gArray[j++];
}
while
((j < mid2) && (k < high))
{
if
(gArray[j].compareTo(gArray[k]) <
0
)
destArray[l++] = gArray[j++];
else
destArray[l++] = gArray[k++];
}
while
((i < mid1) && (k < high))
{
if
(gArray[i].compareTo(gArray[k]) <
0
)
destArray[l++] = gArray[i++];
else
destArray[l++] = gArray[k++];
}
while
(i < mid1)
destArray[l++] = gArray[i++];
while
(j < mid2)
destArray[l++] = gArray[j++];
while
(k < high)
destArray[l++] = gArray[k++];
}
Time Complexity: In case of 2-way Merge sort we get the equation: T(n) = 2T(n/2) + O(n)
Similarly, in case of 3-way Merge sort we get the equation: T(n) = 3T(n/3) + O(n)
By solving it using Master method, we get its complexity as O(n log 3n).. Although time complexity looks less compared to 2 way merge sort, the time taken actually may become higher because number of comparisons in merge function go higher
http://www.geeksforgeeks.org/binary-search-preferred-ternary-search/
int
ternarySearch(
int
arr[],
int
l,
int
r,
int
x)
{
if
(r >= l)
{
int
mid1 = l + (r - l)/3;
int
mid2 = mid1 + (r - l)/3;
if
(arr[mid1] == x)
return
mid1;
if
(arr[mid2] == x)
return
mid2;
if
(arr[mid1] > x)
return
ternarySearch(arr, l, mid1-1, x);
if
(arr[mid2] < x)
return
ternarySearch(arr, mid2+1, r, x);
return
ternarySearch(arr, mid1+1, mid2-1, x);
}
return
-1;
}
Which of the above two does less comparisons in worst case?
From the first look, it seems the ternary search does less number of comparisons as it makes Log3n recursive calls, but binary search makes Log2n recursive calls. Let us take a closer look.
The following is recursive formula for counting comparisons in worst case of Binary Search.
T(n) = T(n/2) + 2, T(1) = 1
The following is recursive formula for counting comparisons in worst case of Ternary Search.
T(n) = T(n/3) + 4, T(1) = 1
In binary search, there are 2Log2n + 1 comparisons in worst case. In ternary search, there are 4Log3n + 1 comparisons in worst case.
Time Complexity for Binary search = 2clog2n + O(1)
Time Complexity for Ternary search = 4clog3n + O(1)
Therefore, the comparison of Ternary and Binary Searches boils down the comparison of expressions 2Log3n and Log2n . The value of 2Log3n can be written as (2 / Log23) * Log2n . Since the value of (2 / Log23) is more than one, Ternary Search does more comparisons than Binary Search in worst case.
https://www.quora.com/Algorithms-How-does-merge-sort-have-space-complexity-O-n-for-worst-case
Mergesort, if implemented to create arrays in the recursive calls, will create many of them, but they won't coexist at the same time. In every recursive call you create an array (or 2 depending on an implementation) for merging and they take no more than O(n) space, and then when the merging is done, these arrays are deleted and some new ones will be created after a moment in some other recursive call. If you counted how much space all the arrays that ever have been created took, it'd be O(n log n), but you don't need to care about this information - you don't need more than O(n) space, because when you need to create an array, all the other ones don't longer exist and don't occupy any memory. Note that you can simply declare 2 - or 3 - arrays in the beginning, each the length of n, and then store the sequence in one of them, while using the other for merging, it will improve the performance as well as show you beyond doubt there's no need for more than O(n) of memory.