Day 46 —— Quick Sort
1. Background
今天是学习java的第46天,今天的内容是快速排序。
2. Description
快速排序的思想非常的简单,先找一个锚点,老师的代码是把每个序列的最后一个元素当作这个锚点,然后分别从头和尾*(这里的尾是锚点的前一个元素)*开始遍历。首先是从前开始遍历,此时遍历的元素必须都比锚点小。如果比锚点大,那就开始从尾遍历,从未开始的元素必须比锚点大,如果比锚点小那就和那个从前开始遍历并比锚点大的元素交换位置。
上面差不多就是快速排序的基本思想了。可以简化为:
- 选定Pivot锚点。
- 将大于Pivot锚点的元素放在后面。
- 将小于Pivot锚点的元素放在前面。
- 对所有子序列重复上面操作。
从这个简化的思想可以看出,操作差不多是重复的,只是要对不同的子对象进行操作。这是我们可以想到,使用递归无疑是非常好用的。
3. Code
package datastructure.search;
public class DataArray {
class DataNode {
// The key.
int key;
// The data content
String content;
// The first constructor.
DataNode(int paraKey, String paraContent) {
key = paraKey;
content = paraContent;
}// Of the second constructor
// Overrides the toString.
public String toString() {
return "(" + key + ", " + content + ") ";
}// Of toString
} // Of class DataNode
// The data array.
DataNode[] data;
// The length of data array.
int length;
/**
*********************
* The first constructor.
*
* @param paraKeyArray The array of the keys.
* @param paraContentArray The array of contents.
*********************
*/
public DataArray(int[] paraKeyArray, String[] paraContentArray) {
length = paraKeyArray.length;
data = new DataNode[length];
for (int i = 0; i < length; i++) {
data[i] = new DataNode(paraKeyArray[i], paraContentArray[i]);
} // Of for i
}// Of the first constructor
// Overrides the toString,
public String toString() {
String resultString = "I am a data array with " + length + " items.\r\n";
for (int i = 0; i < length; i++) {
resultString += data[i] + " ";
} // Of for i
return resultString;
}// Of toString
public String sequentialSearch(int paraKey) {
data[0].key = paraKey;
// 这里虽然是一个简单的顺序查找,但我仍然要说一句,老师的代码真的好简单。
// 我在写的时候就无脑遍历,完全没有下面代码这样简洁。
int i; // 注意,这里不能把i写到for里面去,因为后面需要return data[i],所以i不能是局部变量。
for (i = length - 1; data[i].key != paraKey; i--) {
continue;
}//Of for i
return data[i].content;
} // Of sequentialSearch
// Test sequentialSearch.
public static void sequentialSearchTest() {
int[] tempUnsortedKeys = { -1, 5, 3, 6, 10, 7, 1, 9 };
String[] tempContents = { "null", "if", "then", "else", "switch", "case", "for", "while" };
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);
System.out.println(tempDataArray);
System.out.println("Search result of 10 is: " + tempDataArray.sequentialSearch(10));
System.out.println("Search result of 5 is: " + tempDataArray.sequentialSearch(5));
System.out.println("Search result of 4 is: " + tempDataArray.sequentialSearch(4));
}// Of sequentialSearchTest
/**
************
* 折半查找,相当于数学上的二分法。有一定的局限性,必须要数据有序排列。
*
* @param paraKey The given key.
* @return The content of the key.
************
*/
public String binarySearch(int paraKey) {
int tempLeft = 0;
int tempRight = length - 1;
int tempMiddle = (tempLeft + tempRight) / 2;
while (tempLeft <= tempRight) {
tempMiddle = (tempLeft + tempRight) / 2;
if (data[tempMiddle].key == paraKey) {
return data[tempMiddle].content;
} else if (data[tempMiddle].key <= paraKey) {
tempLeft = tempMiddle + 1;
} else {
tempRight = tempMiddle - 1;
}
} // Of while
// Not found.
return "null";
}// Of binarySearch
public static void binarySearchTest() {
int[] tempSortedKeys = { 1, 3, 5, 6, 7, 9, 10 };
String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
DataArray tempDataArray = new DataArray(tempSortedKeys, tempContents);
System.out.println(tempDataArray);
System.out.println("Search result of 10 is: " + tempDataArray.binarySearch(10));
System.out.println("Search result of 5 is: " + tempDataArray.binarySearch(5));
System.out.println("Search result of 4 is: " + tempDataArray.binarySearch(4));
}// Of binarySearchTest
/**
*********************
* The second constructor. 用哈希表的方法存储数据。
*
* @param paraKeyArray The array of the keys.
* @param paraContentArray The array of contents.
* @param paraLength The space for the Hash table.
*********************
*/
public DataArray(int[] paraKeyArray, String[] paraContentArray, int paraLength) {
// step 1. Initialize.
length = paraLength;
data = new DataNode[length];
for (int i = 0; i < length; i++) {
data[i] = null;
} // Of for i
// step 2. hash
int tempPosition;
for (int i = 0; i < paraKeyArray.length; i++) {
tempPosition = paraKeyArray[i] % length;
while (data[tempPosition] != null) {
tempPosition = (tempPosition + 1) % length;
System.out.println("Collision, move forward for key " + paraKeyArray[i]);
} // Of while
data[tempPosition] = new DataNode(paraKeyArray[i], paraContentArray[i]);
} // Of for i
}
/**
*********************
* Hash search. 上面的数据是用哈希表的方法存的,下面是要找到要存的数据,所以把上面的算法逆转过来即可。
*
* @param paraKey The given key.
* @return The content of the key.
*********************
*/
public String hashSearch(int paraKey) {
int tempPosition = paraKey % length;
while (data[tempPosition] != null) {
if (data[tempPosition].key == paraKey) {
return data[tempPosition].content;
} // Of if
System.out.println("Not this one for " + paraKey);
tempPosition = (tempPosition + 1) % length;
} // Of while
return "null";
}// Of hashSearch
/**
*********************
* Test the method.
*********************
*/
public static void hashSearchTest() {
int[] tempUnsortedKeys = { 16, 33, 38, 69, 57, 95, 86 };
String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents, 19);
System.out.println(tempDataArray);
System.out.println("Search result of 95 is: " + tempDataArray.hashSearch(95));
System.out.println("Search result of 38 is: " + tempDataArray.hashSearch(38));
System.out.println("Search result of 57 is: " + tempDataArray.hashSearch(57));
System.out.println("Search result of 4 is: " + tempDataArray.hashSearch(4));
}// Of hashSearchTest
/**
*********************
* Insertion sort.其中0号元素依然没有存有效数据。
*********************
*/
public void InsertionSort() {
DataNode tempNode;
int j;
for (int i = 2; i < length; i++) {
tempNode = data[i];
for (j = i - 1; data[j].key > tempNode.key; j--) {
data[j + 1] = data[j];
} // Of for j
data[j + 1] = tempNode; // 因为上面循环最后一句是j--,此时j已经运行到了我们要插入的那个位置的前一个坑位,所以这里是data[j + 1]。
System.out.println("Round " + (i - 1));
System.out.println(this);
} // Of for i
} // Of InsertionSort
/**
*********************
* Test the method.
*********************
*/
public static void InsertionSortTest() {
int[] tempUnsortedKeys = { -100, 5, 3, 6, 10, 7, 1, 9 };
String[] tempContents = { "null", "if", "then", "else", "switch", "case", "for", "while" };
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);
System.out.println(tempDataArray);
tempDataArray.InsertionSort();
System.out.println("Result\r\n" + tempDataArray);
}// Of insertionSortTest
/**
*********************
* Shell sort. We do not use sentries here because too many of them are needed.
*********************
*/
public void ShellSort() {
DataNode tempNode;
int[] tempJumpArray = { 5, 3, 1 };
int tempJump;
int p;
for (int i = 0; i < tempJumpArray.length; i++) {
tempJump = tempJumpArray[i];
for (int j = 0; j < tempJump; j++) {
for (int k = j + tempJump; k < length; k += tempJump) {
tempNode = data[k];
for (p = k - tempJump; p >= 0; p -= tempJump) {
if (data[p].key > tempNode.key) {
data[p + tempJump] = data[p];
} else {
break;
} // Of if
} // Of for p
// Insert.
data[p + tempJump] = tempNode;
} // Of for k
} // Of for j
System.out.println("Round " + i);
System.out.println(this);
} // Of for i
}// Of shellSort
/**
*********************
* Test the method.
*********************
*/
public static void ShellSortTest() {
int[] tempUnsortedKeys = { 5, 3, 6, 10, 7, 1, 9, 12, 8, 4 };
String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while", "throw", "until", "do" };
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);
System.out.println(tempDataArray);
tempDataArray.ShellSort();
System.out.println("Result\r\n" + tempDataArray);
}// Of shellSortTest
public void BubbleSort() {
boolean tempSwapped;
DataNode tempNode;
for (int i = length - 1; i > 1; i--) {
tempSwapped = true;
for (int j = 0; j < i; j++) {
if (data[j].key > data[j + 1].key) {
tempNode = data[j];
data[j] = data[j + 1];
data[j + 1] = tempNode;
tempSwapped = false;
} // Of if
} // Of for j
// 这里如果temp还是tree,就说明上面一遍循环下来if语句就没触发过,这个说明数据全部是有序的。
if (tempSwapped) {
System.out.println("Premature");
break;
} // Of if
} // Of for i
} // Of BubbleSort
/**
*********************
* Test the method.
*********************
*/
public static void BubbleSortTest() {
int[] tempUnsortedKeys = { 1, 3, 6, 10, 7, 5, 9 };
String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);
System.out.println(tempDataArray);
tempDataArray.BubbleSort();
System.out.println("Result\r\n" + tempDataArray);
}// Of BubbleSortTest
/**
*********************
* Quick sort recursively.
*
* @param paraStart The start index.
* @param paraEnd The end index.
*********************
*/
public void quickSortRecursive(int paraStart, int paraEnd) {
// 这里是递归的退出语句。当开始节点在结束节点之后表示这个分区的排序已完成。
if (paraStart >= paraEnd) {
return;
} // Of if
int tempPivot = data[paraEnd].key;
DataNode tempNodeForSwap;
int tempLeft = paraStart;
int tempRight = paraEnd - 1;
// 快速排序的具体内容开始。
while (true) {
while ((data[tempLeft].key < tempPivot) && (tempLeft < tempRight)) {
tempLeft++;
} // Of while
while ((data[tempRight].key >= tempPivot) && (tempLeft < tempRight)) {
tempRight--;
} // Of while
if (tempLeft < tempRight) {
// Swap.
System.out.println("Swapping " + tempLeft + " and " + tempRight);
tempNodeForSwap = data[tempLeft];
data[tempLeft] = data[tempRight];
data[tempRight] = tempNodeForSwap;
} else {
break;
} // Of if
} // Of while
// Swap.
if (data[tempLeft].key > tempPivot) {
tempNodeForSwap = data[paraEnd];
data[paraEnd] = data[tempLeft];
data[tempLeft] = tempNodeForSwap;
} else {
tempLeft++;
} // Of if
System.out.print("From " + paraStart + " to " + paraEnd + ": ");
System.out.println(this);
quickSortRecursive(paraStart, tempLeft - 1);
quickSortRecursive(tempLeft + 1, paraEnd);
}// Of quickSortRecursive
/**
*********************
* Quick sort.
*********************
*/
public void quickSort() {
quickSortRecursive(0, length - 1);
}// Of quickSort
/**
*********************
* Test the method.
*********************
*/
public static void quickSortTest() {
int[] tempUnsortedKeys = { 1, 3, 12, 10, 5, 7, 9 };
String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);
System.out.println(tempDataArray);
tempDataArray.quickSort();
System.out.println("Result\r\n" + tempDataArray);
}// Of quickSortTest
/**
************
* The entrance of the program.
*
* @param args Not used now.
************
*/
public static void main(String args[]) {
System.out.println("\r\n-------sequentialSearchTest-------");
sequentialSearchTest();
System.out.println("\r\n-------binarySearchTest-------");
binarySearchTest();
System.out.println("\r\n-------hashSearchTest-------");
hashSearchTest();
System.out.println("\r\n-------InsertionSortTest-------");
InsertionSortTest();
System.out.println("\r\n-------ShellSortTest-------");
ShellSortTest();
System.out.println("\r\n-------BubbleSortTes-------");
BubbleSortTest();
System.out.println("\r\n-------quickSortTest-------");
quickSortTest();
}// Of main
}
运行结果: