说明
闵老师的文章链接: 日撸 Java 三百行(总述)_minfanphd的博客-优快云博客
自己也把手敲的代码放在了github上维护:https://github.com/fulisha-ok/sampledata
day49 归并排序
1.基本思路
归并是将两个或两个以上的有序表组合成一个新的有序表,归并排序是分治思想的应用(分而治之)。如下是手动模拟二路归并排序,如下有7个数:
进行两两排序,得⌈7/2⌉=4(向上取整)有4个长度为2或1的分组,对每个分组进行排序,再进行⌈7/4⌉=2 有2个长度为4或3的分组,进行分组排序后,⌈7/7⌉=1 长度为7的一个分组,对这个分组进行排序。如下图所示
-------mergeSortTest-------
I am a data array with 7 items.
(50, if) (39, then) (66, else) (98, switch) (77, case) (14, for) (28, while)
(50, if)
(39, then)
(66, else)
(98, switch)
(77, case)
(14, for)
(28, while)
Current row = 0
tempSize = 1, numGroups = 4
Trying to merge [0, 0] with [1, 1]
copying (39, then)
Trying to merge [2, 2] with [3, 3]
copying (98, switch)
Trying to merge [4, 4] with [5, 5]
copying (14, for)
Round 0
(39, then) (50, if) (66, else) (98, switch) (14, for) (77, case) (28, while)
Current row = 1
tempSize = 2, numGroups = 2
Trying to merge [0, 1] with [2, 3]
copying (50, if)
copying (66, else)
Trying to merge [4, 5] with [6, 6]
copying (77, case)
copying (28, while)
Round 1
(39, then) (50, if) (66, else) (98, switch) (14, for) (28, while) (77, case)
Current row = 2
tempSize = 4, numGroups = 1
Trying to merge [0, 3] with [4, 6]
copying (14, for)
copying (28, while)
copying (50, if)
copying (66, else)
copying (98, switch)
copying (77, case)
Round 2
(14, for) (28, while) (39, then) (50, if) (66, else) (77, case) (98, switch)
I am a data array with 7 items.
(14, for) (28, while) (39, then) (50, if) (66, else) (77, case) (98, switch)
2.代码实现
这段代码是非递归实现归并排序,我觉得读起来还是挺有难度的,首先是他的变量太多,其次在为每一次排序时,分多少组,分组长度不一致怎么解决以及分好组后如何进行排序等一些比较细节的东西。所以在段代码是需要结合图形来看才能更好的吸收内容
/**
* merge sort. Results are stored in the member variable data;
*/
public void mergeSort() {
//step1. Allocate space
int tempRow; // the current row
int tempGroups; // Number of groups
int tempActualRow; // only 0 or 1
int tempNextRow = 0;
int tempGroupNumber;
int tempFirstStart, tempSecondStart, tempSecondEnd;
int tempFirstIndex, tempSecondIndex;
int tempNumCopied;
for (int i = 0; i < length; i++) {
System.out.println(data[i]);
}
System.out.println();
DataNode[][] tempMatrix = new DataNode[2][length];
//step2 copy data
for (int i = 0; i < length; i++) {
tempMatrix[0][i] = data[i];
}
//step3.Merge log n rounds
tempRow = -1;
//进行几趟归并排序 tempSize:一个小组的大小
for (int tempSize = 1; tempSize <= length; tempSize *= 2) {
// Reuse the space of the two rows.
tempRow++;
System.out.println("Current row = " + tempRow);
tempActualRow = tempRow % 2;
tempNextRow = (tempRow + 1) % 2;
// 在每趟排序中需要分为几组 乘以2是因为是2路归并
tempGroups = length / (tempSize * 2);
if (length % (tempSize * 2) != 0) {
tempGroups++;
}
System.out.println("tempSize = " + tempSize + ", numGroups = " + tempGroups);
//对两两分组进行排序
for (tempGroupNumber = 0; tempGroupNumber < tempGroups; tempGroupNumber++) {
//两组的起始位置
tempFirstStart = tempGroupNumber * tempSize * 2;
tempSecondStart = tempGroupNumber * tempSize * 2 + tempSize;
if (tempSecondStart > length - 1) {
// Copy the first part.
for (int i = tempFirstStart; i < length; i++) {
tempMatrix[tempNextRow][i] = tempMatrix[tempActualRow][i];
}
continue;
}
//判断第二个分组与第一个是否等长 不等长则需要调整结尾是长度
tempSecondEnd = tempGroupNumber * tempSize * 2 + tempSize * 2 - 1;
if (tempSecondEnd > length - 1) {
tempSecondEnd = length - 1;
}
System.out
.println("Trying to merge [" + tempFirstStart + ", " + (tempSecondStart - 1)
+ "] with [" + tempSecondStart + ", " + tempSecondEnd + "]");
tempFirstIndex = tempFirstStart;
tempSecondIndex = tempSecondStart;
tempNumCopied = 0;
while ((tempFirstIndex <= tempSecondStart - 1)
&& (tempSecondIndex <= tempSecondEnd)) {
if (tempMatrix[tempActualRow][tempFirstIndex].key <= tempMatrix[tempActualRow][tempSecondIndex].key) {
tempMatrix[tempNextRow][tempFirstStart + tempNumCopied] = tempMatrix[tempActualRow][tempFirstIndex];
tempFirstIndex++;
System.out.println("copying " + tempMatrix[tempActualRow][tempFirstIndex]);
} else {
tempMatrix[tempNextRow][tempFirstStart
+ tempNumCopied] = tempMatrix[tempActualRow][tempSecondIndex];
System.out.println("copying " + tempMatrix[tempActualRow][tempSecondIndex]);
tempSecondIndex++;
}
tempNumCopied++;
}
while (tempFirstIndex <= tempSecondStart - 1) {
tempMatrix[tempNextRow][tempFirstStart + tempNumCopied] = tempMatrix[tempActualRow][tempFirstIndex];
tempFirstIndex++;
tempNumCopied++;
} // Of while
while (tempSecondIndex <= tempSecondEnd) {
tempMatrix[tempNextRow][tempFirstStart + tempNumCopied] = tempMatrix[tempActualRow][tempSecondIndex];
tempSecondIndex++;
tempNumCopied++;
}
}
System.out.println("Round " + tempRow);
for (int i = 0; i < length; i++) {
System.out.print(tempMatrix[tempNextRow][i] + " ");
}
System.out.println();
}
data = tempMatrix[tempNextRow];
}
public static void mergeSortTest() {
//int[] tempUnsortedKeys = { 5, 3, 6, 10, 7, 1, 9 };
int[] tempUnsortedKeys = { 50, 39, 66, 98, 77, 14, 28 };
String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);
System.out.println(tempDataArray);
tempDataArray.mergeSort();
System.out.println(tempDataArray);
}
-------mergeSortTest-------
I am a data array with 7 items.
(5, if) (3, then) (6, else) (10, switch) (7, case) (1, for) (9, while)
(5, if)
(3, then)
(6, else)
(10, switch)
(7, case)
(1, for)
(9, while)
Current row = 0
tempSize = 1, numGroups = 4
Trying to merge [0, 0] with [1, 1]
copying (3, then)
Trying to merge [2, 2] with [3, 3]
copying (10, switch)
Trying to merge [4, 4] with [5, 5]
copying (1, for)
Round 0
(3, then) (5, if) (6, else) (10, switch) (1, for) (7, case) (9, while)
Current row = 1
tempSize = 2, numGroups = 2
Trying to merge [0, 1] with [2, 3]
copying (5, if)
copying (6, else)
Trying to merge [4, 5] with [6, 6]
copying (7, case)
copying (9, while)
Round 1
(3, then) (5, if) (6, else) (10, switch) (1, for) (7, case) (9, while)
Current row = 2
tempSize = 4, numGroups = 1
Trying to merge [0, 3] with [4, 6]
copying (1, for)
copying (5, if)
copying (6, else)
copying (10, switch)
copying (7, case)
copying (9, while)
Round 2
(1, for) (3, then) (5, if) (6, else) (7, case) (9, while) (10, switch)
I am a data array with 7 items.
(1, for) (3, then) (5, if) (6, else) (7, case) (9, while) (10, switch)