1. Insertion Sort
1> Straight Insertion Sort: O(n^2), if the records are already sorted, then O(n).
2> Binary Insertion Sort (Reduced comparison count)
3> 2-Way Insertion Sort (Reduced comparison count and move record time)
4> Shell's Sort
2. Swap Sort
1> Bubble Sort: O(n^2)
2> Quick Sort: O(n*lgn), If the array is already ordered, then Quick Sort degenerated to Bubble Sort.
3. Selection Sort
1> Simple Selection Sort: O(n^2)
2> Tree Selection Sort
4> Heap Sort: O(n*lgn)
4. Merging Sort
5. Radix Sort
1. Insertion Sort
1> Straight Insertion Sort
package edu.xmu.datastructure.sort.insertion;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class StraightInsertionSort {
@Test
public void insertSortTest() {
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
List<Integer> sortedIntList = StraightInsertionSort.insertSort(intList);
assertEquals(expIntList, sortedIntList);
}
public static List<Integer> insertSort(List<Integer> intList) {
List<Integer> sortedIntList = Lists.newArrayList(intList);
for (int i = 1; i < sortedIntList.size(); i++) {
int valueToBeInserted = sortedIntList.get(i);
int indexToBeInserted = i;
for (int j = i - 1; j >= 0; j--) {
if (valueToBeInserted < sortedIntList.get(j)) {
sortedIntList.set(j + 1, sortedIntList.get(j));
indexToBeInserted = j;
} else {
break;
}
}
sortedIntList.set(indexToBeInserted, valueToBeInserted);
}
return sortedIntList;
}
}
2> Binary Insertion Sort
package edu.xmu.datastructure.sort.insertion;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class BinaryInsertionSort {
@Test
public void insertSortTest() {
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
List<Integer> sortedIntList = BinaryInsertionSort
.binaryInsertSort(intList);
assertEquals(expIntList, sortedIntList);
}
public static List<Integer> binaryInsertSort(List<Integer> intList) {
List<Integer> sortedIntList = Lists.newArrayList(intList);
for (int i = 1; i < sortedIntList.size(); i++) {
int valueToBeInserted = sortedIntList.get(i);
int indexToBeInserted = searchIndexToBeInserted(i, sortedIntList);
// Move elements from [indexToBeInserted, i - 1] to
// [indexToBeInserted + 1, i]
for (int j = i - 1; j >= indexToBeInserted; j--) {
if (valueToBeInserted < sortedIntList.get(j)) {
sortedIntList.set(j + 1, sortedIntList.get(j));
}
}
// Insert element to indexToBeInserted position
sortedIntList.set(indexToBeInserted, valueToBeInserted);
}
return sortedIntList;
}
public static int searchIndexToBeInserted(int hotIndex,
List<Integer> sortedIntList) {
int startIndex = 0;
int endIndex = hotIndex - 1;
while (startIndex <= endIndex) {
int middle = (startIndex + endIndex) / 2;
if (sortedIntList.get(hotIndex) < sortedIntList.get(middle)) {
endIndex = middle - 1;
} else {
startIndex = middle + 1;
}
}
return endIndex + 1;
}
@Test
public void searchIndexToBeInsertedTest() {
List<Integer> sortedIntList = Lists.newArrayList(1, 2, 3, 0);
int hotIndex = 3;
int indexToBeInserted = BinaryInsertionSort.searchIndexToBeInserted(
hotIndex, sortedIntList);
assertEquals(0, indexToBeInserted);
sortedIntList = Lists.newArrayList(1, 2, 3, 4, 0);
hotIndex = 4;
indexToBeInserted = BinaryInsertionSort.searchIndexToBeInserted(
hotIndex, sortedIntList);
assertEquals(0, indexToBeInserted);
sortedIntList = Lists.newArrayList(2, 4, 6, 8, 10);
hotIndex = 4;
indexToBeInserted = BinaryInsertionSort.searchIndexToBeInserted(
hotIndex, sortedIntList);
assertEquals(4, indexToBeInserted);
sortedIntList = Lists.newArrayList(2, 4, 6, 8, 10, 5);
hotIndex = 5;
indexToBeInserted = BinaryInsertionSort.searchIndexToBeInserted(
hotIndex, sortedIntList);
assertEquals(2, indexToBeInserted);
}
}
3> Shell's Sort (When we create the deltaList=Lists.newArrayList(1), then Shell's Sort degenerated to Straight Insertion Sort).
package edu.xmu.datastructure.sort.insertion;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class ShellInsertionSort {
@Test
public void insertSortTest() {
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
List<Integer> deltaList = Lists.newArrayList(5, 3, 2, 1);
for (int delta : deltaList) {
ShellInsertionSort.shellInsertSort(intList, delta);
}
assertEquals(expIntList, intList);
}
public static void shellInsertSort(List<Integer> intList, int delta) {
for (int i = delta; i < intList.size(); i++) {
int valueToBeInserted = intList.get(i);
int indexToBeInserted = i;
for (int j = i - delta; j >= 0; j -= delta) {
if (valueToBeInserted < intList.get(j)) {
intList.set(j + delta, intList.get(j));
indexToBeInserted = j;
} else {
break;
}
}
intList.set(indexToBeInserted, valueToBeInserted);
}
}
}
2. Swap Sort
1> Bubble Sort
package edu.xmu.datastructure.sort.swap;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class BubbleSort {
@Test
public void bubbleSortTest() {
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
BubbleSort.bubbleSort(intList);
assertEquals(expIntList, intList);
}
public static void bubbleSort(List<Integer> intList) {
for (int i = 0; i < intList.size(); i++) {
for (int j = 0; j < intList.size() - i - 1; j++) {
int prevValue = intList.get(j);
int currValue = intList.get(j + 1);
// The biggest value bubbles to the end of the list
if (prevValue > currValue) {
intList.set(j, currValue);
intList.set(j + 1, prevValue);
}
}
}
}
}
2> Quick Sort
package edu.xmu.datastructure.sort.swap;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class QuickSort {
@Test
public void quickSortTest() {
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
QuickSort.quickSort(intList, 0, intList.size() - 1);
assertEquals(expIntList, intList);
}
public static void quickSort(List<Integer> intList, int startIndex,
int endIndex) {
if (startIndex < endIndex) {
int pivotIndex = splitList(intList, startIndex, endIndex);
quickSort(intList, startIndex, pivotIndex - 1);
quickSort(intList, pivotIndex + 1, endIndex);
}
}
@Test
public void splitListTest() {
List<Integer> expectedIntList = Lists.newArrayList(27, 38, 13, 49, 76,
97, 65);
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
int newPivotIndex = QuickSort.splitList(intList, 0, 6);
assertEquals(expectedIntList, intList);
assertEquals(3, newPivotIndex);
}
public static int splitList(List<Integer> intList, int pivotIndex, int high) {
int pivotValue = intList.get(pivotIndex);
int low = pivotIndex;
boolean shouldHighMove = true;
while (low < high) {
if (shouldHighMove) {
if (intList.get(high) < pivotValue) {
int lowValue = intList.get(low);
int highValue = intList.get(high);
intList.set(low, highValue);
intList.set(high, lowValue);
low++;
shouldHighMove = false;
} else {
shouldHighMove = true;
high--;
}
} else {
if (intList.get(low) > pivotValue) {
int lowValue = intList.get(low);
int highValue = intList.get(high);
intList.set(low, highValue);
intList.set(high, lowValue);
high--;
shouldHighMove = true;
} else {
shouldHighMove = false;
low++;
}
}
}
if (high != low) {
throw new RuntimeException("Defacted Algorithm!");
}
intList.set(low, pivotValue);
return low;
}
}
3. Selection Sort
1> Simple Selection Sort
package edu.xmu.datastructure.sort.selection;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class SimpleSelectionSort {
@Test
public void insertSortTest() {
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
SimpleSelectionSort.selectionSort(intList);
assertEquals(expIntList, intList);
}
public static void selectionSort(List<Integer> intList) {
int minValue;
int indexToBeSwapped;
for (int i = 0; i < intList.size(); i++) {
minValue = Integer.MAX_VALUE;
indexToBeSwapped = 0;
for (int j = i; j < intList.size(); j++) {
int temp = intList.get(j);
if (minValue > temp) {
minValue = temp;
indexToBeSwapped = j;
}
}
int value = intList.get(i);
intList.set(i, minValue);
intList.set(indexToBeSwapped, value);
}
}
}
Simple Selection Sort (Extract getMinValueIndex out, make code easier to read)
package edu.xmu.datastructure.sort.selection;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class SimpleSelectionSort {
@Test
public void insertSortTest() {
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
SimpleSelectionSort.selectionSort(intList);
assertEquals(expIntList, intList);
}
public static void selectionSort(List<Integer> intList) {
for (int i = 0; i < intList.size(); i++) {
int minValueIndex = getMinValueIndex(i, intList);
int minValue = intList.get(minValueIndex);
int tempValue = intList.get(i);
intList.set(i, minValue);
intList.set(minValueIndex, tempValue);
}
}
private static int getMinValueIndex(int startIndex, List<Integer> intList) {
int minValue = Integer.MAX_VALUE;
int minValueIndex = 0;
for (int j = startIndex; j < intList.size(); j++) {
int temp = intList.get(j);
if (minValue > temp) {
minValue = temp;
minValueIndex = j;
}
}
return minValueIndex;
}
}
2> Tree Selection Sort (Tournament Sort): It's just a transition selection sort algorithm between "Simple Selection Sort" and "Heap Sort"
package edu.xmu.datastructure.sort.selection;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class TreeSelectionSort {
@Test
public void selectionSortTest() {
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
List<Integer> orderedIntList = TreeSelectionSort
.treeSelectionSort(intList);
assertEquals(expIntList, orderedIntList);
}
public static List<Integer> treeSelectionSort(List<Integer> intList) {
BinarySelectionTreeNode rootNode = buildTree(intList);
List<Integer> orderedIntList = Lists.newArrayListWithCapacity(intList
.size());
int minValue;
for (int i = 0; i < intList.size(); i++) {
rootNode.reElectMinValue();
minValue = rootNode.getValue();
orderedIntList.add(minValue);
rootNode.removeMinValue(minValue);
}
return orderedIntList;
}
public static BinarySelectionTreeNode buildTree(List<Integer> intList) {
List<BinarySelectionTreeNode> leafNodes = Lists
.newArrayListWithExpectedSize(intList.size());
for (int value : intList) {
BinarySelectionTreeNode leafNode = new BinarySelectionTreeNode();
leafNode.setValue(value);
leafNodes.add(leafNode);
}
List<BinarySelectionTreeNode> rootNode = buildFromNodes(leafNodes);
return rootNode.get(0);
}
private static List<BinarySelectionTreeNode> buildFromNodes(
List<BinarySelectionTreeNode> nodes) {
if (nodes.size() <= 1) {
return nodes;
}
if (nodes.size() % 2 != 0) {
nodes.add(new BinarySelectionTreeNode());
}
List<BinarySelectionTreeNode> mergedNodes = Lists
.newArrayListWithCapacity(nodes.size() / 2);
for (int i = 0; i < nodes.size(); i += 2) {
BinarySelectionTreeNode mergedNode = new BinarySelectionTreeNode();
BinarySelectionTreeNode lChildNode = nodes.get(i);
BinarySelectionTreeNode rChildNode = nodes.get(i + 1);
mergedNode.setlChild(lChildNode);
mergedNode.setrChild(rChildNode);
mergedNodes.add(mergedNode);
}
return buildFromNodes(mergedNodes);
}
public static class BinarySelectionTreeNode {
private int value = Integer.MAX_VALUE;
private BinarySelectionTreeNode lChild;
private BinarySelectionTreeNode rChild;
public void removeMinValue(int minValue) {
if (null == lChild && null == rChild) {
if (minValue == this.value) {
this.value = Integer.MAX_VALUE;
}
} else {
if (this.value == minValue) {
this.value = Integer.MAX_VALUE;
lChild.removeMinValue(minValue);
rChild.removeMinValue(minValue);
}
}
}
public int reElectMinValue() {
int minValue = Integer.MAX_VALUE;
if (null == lChild && null == rChild) {
minValue = this.value;
} else {
int lMinValue = lChild.reElectMinValue();
int rMinValue = rChild.reElectMinValue();
minValue = lMinValue < rMinValue ? lMinValue : rMinValue;
}
this.value = minValue;
return minValue;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public BinarySelectionTreeNode getlChild() {
return lChild;
}
public void setlChild(BinarySelectionTreeNode lChild) {
this.lChild = lChild;
}
public BinarySelectionTreeNode getrChild() {
return rChild;
}
public void setrChild(BinarySelectionTreeNode rChild) {
this.rChild = rChild;
}
}
}
3> Heap Sort
package edu.xmu.datastructure.sort.selection;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class HeapSort {
@Test
public void heapSortTest() {
// 49
// 38 65
// 97 76 13 27
List<Integer> intList = Lists.newArrayList(Integer.MAX_VALUE, 49, 38,
65, 97, 76, 13, 27);
List<Integer> expIntList = Lists.newArrayList(Integer.MAX_VALUE, 13,
27, 38, 49, 65, 76, 97);
HeapSort.heapSort(intList);
assertEquals(expIntList, intList);
}
public static void heapSort(List<Integer> intList) {
for (int i = intList.size() / 2; i >= 1; i--) {
adjustHeap(intList, i, intList.size() - 1);
}
for (int i = intList.size() - 1; i >= 1; i--) {
int maxValue = intList.get(1);
int tailValue = intList.get(i);
intList.set(1, tailValue);
intList.set(i, maxValue);
adjustHeap(intList, 1, i - 1);
}
}
// Max Heap
private static void adjustHeap(List<Integer> intList, int startIndex,
int endIndex) {
int rootNodeValue = intList.get(startIndex);
int currentIndex = startIndex;
for (int i = startIndex * 2; i <= endIndex; i *= 2) {
if (i + 1 > endIndex) {
// For the benefit of obsolete index
// When we put the max value at the end of array
// Then [start, end - 1]
// But here intList.get(i + 1) may unintentionally get the
// already set as max and thus unreachable
} else if (intList.get(i) < intList.get(i + 1)) {
i += 1;
}
if (rootNodeValue > intList.get(i)) {
// rootNode is bigger than its children
break;
}
intList.set(currentIndex, intList.get(i));
currentIndex = i;
}
intList.set(currentIndex, rootNodeValue);
}
}
4. Merge Sort
package edu.xmu.datastructure.sort.merge;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Lists;
public class MergeSort {
@Test
public void mergeSortTest() {
List<Integer> intList = Lists.newArrayList(49, 38, 65, 97, 76, 13, 27);
List<Integer> expIntList = Lists.newArrayList(13, 27, 38, 49, 65, 76,
97);
List<Integer> sortedIntList = MergeSort.mergeSort(intList, 0,
intList.size() - 1);
assertEquals(expIntList, sortedIntList);
}
public static List<Integer> mergeSort(List<Integer> intList,
int startIndex, int endIndex) {
List<Integer> mergedList;
if (startIndex == endIndex) {
mergedList = Lists.newArrayList(intList.get(startIndex));
} else {
int middleIndex = (startIndex + endIndex) / 2;
List<Integer> leftList = mergeSort(intList, startIndex, middleIndex);
List<Integer> rightList = mergeSort(intList, middleIndex + 1,
endIndex);
mergedList = mergeSortedList(leftList, rightList);
}
return mergedList;
}
@Test
public void mergeListTest() {
List<Integer> leftList = Lists.newArrayList(1, 3, 5, 7);
List<Integer> rightList = Lists.newArrayList(0, 2);
List<Integer> expectedMergedList = Lists.newArrayList(0, 1, 2, 3, 5, 7);
List<Integer> mergedList = MergeSort.mergeSortedList(leftList,
rightList);
assertEquals(expectedMergedList, mergedList);
leftList = Lists.newArrayList(1, 3, 5, 7);
rightList = Lists.newArrayList(0, 2, 4, 6, 8, 9);
expectedMergedList = Lists.newArrayList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
mergedList = MergeSort.mergeSortedList(leftList, rightList);
assertEquals(expectedMergedList, mergedList);
}
/**
* Merge two ascending sorted list into one single asc list
*
* @param leftList
* @param rightList
* @return
*/
public static List<Integer> mergeSortedList(List<Integer> leftList,
List<Integer> rightList) {
List<Integer> mergedList = Lists.newArrayList();
int leftSize = leftList.size();
int rightSize = rightList.size();
int leftIndex = 0;
int rightIndex = 0;
int leftValue = Integer.MAX_VALUE;
int rightValue = Integer.MAX_VALUE;
while (!(leftIndex == leftSize && rightIndex == rightSize)) {
if (leftIndex < leftSize) {
leftValue = leftList.get(leftIndex);
} else {
leftValue = Integer.MAX_VALUE;
}
if (rightIndex < rightSize) {
rightValue = rightList.get(rightIndex);
} else {
rightValue = Integer.MAX_VALUE;
}
if (rightValue < leftValue) {
mergedList.add(rightValue);
rightIndex++;
} else {
mergedList.add(leftValue);
leftIndex++;
}
}
return mergedList;
}
}
Reference Links:
1> http://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html
2> "Data Structure(C version)" - Yan, Weimin