41-50

第 41 天: 顺序查找与折半查找

顺序查找使用岗哨可以节约一半的时间. 为此, 第 0 个位置不可以放有意义的数据, 即有效数据只有 length - 1 个.
顺序查找时间复杂度为 O ( n ) O(n)O(n).
折半查找时间复杂度为 O ( log ⁡ n ) O(\log n)O(logn).
书上为简化起见, 只关注键. 这里使用键值对来表示一条完整的数据. 实际应用中可以把 content 改成任何想要的数据类型.

代码如下:

package days41_50;


public class DataArray {

	class DataNode {
		
		int key;

		String content;

		DataNode(int paraKey, String paraContent) {
			key = paraKey;
			content = paraContent;
		}// Of the second constructor


		public String toString() {
			return "(" + key + ", " + content + ") ";
		}// Of toString
	}// Of class DataNode

	DataNode[] data;


	int length;

	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


	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;
		// Note that we do not judge i >= 0 since data[0].key = paraKey.
		// In this way the runtime is saved about 1/2.
		for (i = length - 1; data[i].key != paraKey; i--)
			;

		return data[i].content;
	}// Of 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


	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
	

	public static void main(String args[]) {
		System.out.println("\r\n-------sequentialSearchTest-------");
		sequentialSearchTest();

		System.out.println("\r\n-------binarySearchTest-------");
		binarySearchTest();
	}// Of main

}// Of class DataArray

运行结果:


-------sequentialSearchTest-------
I am a data array with 8 items.
(-1, null)  (5, if)  (3, then)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  
Search result of 10 is: switch
Search result of 5 is: if
Search result of 4 is: null

-------binarySearchTest-------
I am a data array with 7 items.
(1, if)  (3, then)  (5, else)  (6, switch)  (7, case)  (9, for)  (10, while)  
Search result of 10 is: while
Search result of 5 is: else
Search result of 4 is: null

第 42 天: 哈希表

任务:
神奇、实用、粗暴的方法. 空间换时间.
保证空间足够.
在构造方法中装入数据. 自己可以写代码增加数据.
使用 (最简单的) 除数取余法获得数据存放地址 (下标).
使用 (最简单的) 顺移位置法解决冲突.
搜索的时间复杂度仅与冲突概率相关, 间接地就与装填因子相关. 如果空间很多, 可以看出时间复杂度为O(1).

今天的代码在昨天的基础上进行,新增代码如下:


	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. Fill the data.
		int tempPosition;

		for (int i = 0; i < paraKeyArray.length; i++) {
			// Hash.
			tempPosition = paraKeyArray[i] % paraLength;

			// Find an empty position
			while (data[tempPosition] != null) {
				tempPosition = (tempPosition + 1) % paraLength;
				System.out.println("Collision, move forward for key " + paraKeyArray[i]);
			} // Of while

			data[tempPosition] = new DataNode(paraKeyArray[i], paraContentArray[i]);
		} // Of for i
	}// Of the second constructor

	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

	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

	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();
	}// Of main

运行结果:

-------hashSearchTest-------
Collision, move forward for key 57
Collision, move forward for key 95
Collision, move forward for key 95
I am a data array with 19 items.
(38, else)  (57, case)  (95, for)  null null null null null null null (86, while)  null (69, switch)  null (33, then)  null (16, if)  null null 
Not this one for 95
Not this one for 95
Search result of 95 is: for
Search result of 38 is: else
Not this one for 57
Search result of 57 is: case
Search result of 4 is: null

补充:
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

记录的存储位置=f(关键字)

这里的对应关系f称为散列函数,又称为哈希(Hash函数),采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash table)。

哈希表hashtable(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。(或者:把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。)
而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。

数组的特点是:寻址容易,插入和删除困难;

而链表的特点是:寻址困难,插入和删除容易。
哈希表

第 43 天: 插入排序

注意:
插入排序是简单直接的排序方式之一. 代码非常短.
每次保证前 i 个数据是有序的.
先做简单的事情 (第 1 轮最多有 1 次移动), 再做麻烦的事情 (最后一轮最多有 n − 1 n - 1n−1 次移动).
下标 0 的数据为岗哨, 与 41 天内容同理. 比其它排序方式多用一个空间.
又见 this.
tempNode 只分配了引用 (指针) 的空间, 并未 new.

今天新增的代码如下:


	public void insertionSort() {
		DataNode tempNode;
		int j;
		for (int i = 2; i < length; i++) {
			tempNode = data[i];
			
			//Find the position to insert.
			//At the same time, move other nodes.
			for (j = i - 1; data[j].key > tempNode.key; j--) {
				data[j + 1] = data[j];
			} // Of for j
			
			//Insert.
			data[j + 1] = tempNode;
			
			System.out.println("Round " + (i - 1));
			System.out.println(this);
		} // Of for i
	}// Of insertionSort

	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

运行结果:

-------insertionSortTest-------
I am a data array with 8 items.
(-100, null)  (5, if)  (3, then)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  
Round 1
I am a data array with 8 items.
(-100, null)  (3, then)  (5, if)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  
Round 2
I am a data array with 8 items.
(-100, null)  (3, then)  (5, if)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  
Round 3
I am a data array with 8 items.
(-100, null)  (3, then)  (5, if)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  
Round 4
I am a data array with 8 items.
(-100, null)  (3, then)  (5, if)  (6, else)  (7, case)  (10, switch)  (1, for)  (9, while)  
Round 5
I am a data array with 8 items.
(-100, null)  (1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (10, switch)  (9, while)  
Round 6
I am a data array with 8 items.
(-100, null)  (1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Result
I am a data array with 8 items.
(-100, null)  (1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  

第 44 天: 希尔排序

多达 4 重循环, 但时间复杂度只有O(n^2)。
多次排序反正减少了平均排序时间. 神奇的脑回路.
有了昨天的程序铺垫, 本程序写起来也不难.
岗哨的个数与最初的步长相关, 我们的程序中为 5. 简便起见我就没用了.
可以改变 tempJumpArray.
测试用例多用了几个数据, 便于观察.

test代码如下:


	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];
					// Find the position to insert.
					// At the same time, move other nodes.
					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

	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

运行结果:

-------shellSortTest-------
I am a data array with 10 items.
(5, if)  (3, then)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  (12, throw)  (8, until)  (4, do)  
Round 0
I am a data array with 10 items.
(1, for)  (3, then)  (6, else)  (8, until)  (4, do)  (5, if)  (9, while)  (12, throw)  (10, switch)  (7, case)  
Round 1
I am a data array with 10 items.
(1, for)  (3, then)  (5, if)  (7, case)  (4, do)  (6, else)  (8, until)  (12, throw)  (10, switch)  (9, while)  
Round 2
I am a data array with 10 items.
(1, for)  (3, then)  (4, do)  (5, if)  (6, else)  (7, case)  (8, until)  (9, while)  (10, switch)  (12, throw)  
Result
I am a data array with 10 items.
(1, for)  (3, then)  (4, do)  (5, if)  (6, else)  (7, case)  (8, until)  (9, while)  (10, switch)  (12, throw)  

第 45 天: 冒泡排序

每次确定当前最大值, 也就是确定一个位置的数据.
仅交换相邻数据.
如果某一趟没有交换, 就表示数据已经有序 (早熟, premature), 可以提前结束了.

新增代码如下:


	public void bubbleSort() {
		boolean tempSwapped;
		DataNode tempNode;
		for (int i = length - 1; i > 1; i--) {
			tempSwapped = false;
			for (int j = 0; j < i; j++) {
				if (data[j].key > data[j + 1].key) {
					// Swap.
					tempNode = data[j + 1];
					data[j + 1] = data[j];
					data[j] = tempNode;

					tempSwapped = true;
				} // Of if
			} // Of for j

			// No swap in this round. The data are already sorted.
			if (!tempSwapped) {
				System.out.println("Premature");
				break;
			} // Of if

			System.out.println("Round " + (length - i));
			System.out.println(this);
		} // Of for i
	}// Of bubbleSort

	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

运行结果:

-------bubbleSortTest-------
I am a data array with 7 items.
(1, if)  (3, then)  (6, else)  (10, switch)  (7, case)  (5, for)  (9, while)  
Round 1
I am a data array with 7 items.
(1, if)  (3, then)  (6, else)  (7, case)  (5, for)  (9, while)  (10, switch)  
Round 2
I am a data array with 7 items.
(1, if)  (3, then)  (6, else)  (5, for)  (7, case)  (9, while)  (10, switch)  
Round 3
I am a data array with 7 items.
(1, if)  (3, then)  (5, for)  (6, else)  (7, case)  (9, while)  (10, switch)  
Premature
Result
I am a data array with 7 items.
(1, if)  (3, then)  (5, for)  (6, else)  (7, case)  (9, while)  (10, switch)  

第 46 天: 快速排序

平均时间复杂度为 O(nlogn), 但最坏情况还是O(n^2
Pivot 应该选 (该子序列的) 最后一个元素.
递归算法, 每次只能确定 pivot 的位置.
判断条件 && (tempLeft < tempRight) 不能少.

新增代码如下:


	public void quickSortRecursive(int paraStart, int paraEnd) {
		// Nothing to sort.
		if (paraStart >= paraEnd) {
			return;
		} // Of if

		int tempPivot = data[paraEnd].key;
		DataNode tempNodeForSwap;

		int tempLeft = paraStart;
		int tempRight = paraEnd - 1;

		// Find the position for the pivot.
		// At the same time move smaller elements to the left and bigger one to the
		// right.
		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

	public void quickSort() {
		quickSortRecursive(0, length - 1);
	}// Of quickSort


	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

运行结果:

I am a data array with 7 items.
(1, if)  (3, then)  (12, else)  (10, switch)  (5, case)  (7, for)  (9, while)  
Swapping 2 and 5
Swapping 3 and 4
From 0 to 6: I am a data array with 7 items.
(1, if)  (3, then)  (7, for)  (5, case)  (9, while)  (12, else)  (10, switch)  
From 0 to 3: I am a data array with 7 items.
(1, if)  (3, then)  (5, case)  (7, for)  (9, while)  (12, else)  (10, switch)  
From 0 to 1: I am a data array with 7 items.
(1, if)  (3, then)  (5, case)  (7, for)  (9, while)  (12, else)  (10, switch)  
From 5 to 6: I am a data array with 7 items.
(1, if)  (3, then)  (5, case)  (7, for)  (9, while)  (10, switch)  (12, else)  
Result
I am a data array with 7 items.
(1, if)  (3, then)  (5, case)  (7, for)  (9, while)  (10, switch)  (12, else)  

冒泡更好理解一些

第 47 天: 选择排序

又是一个基础 (简单) 算法.
与插入排序不同, 先做最麻烦的, 要进行 n − 1 n - 1n−1 次比较才能获得最小的数据.
数据一旦被选择并确定位置, 就不再改变.
做为一种简单算法, 其时间复杂度为 O(n^2)
只需要两个额外的空间来存放最小数据的引用与下标, 因此空间复杂度为 O(1)

新增代码如下:


	public void selectionSort() {
		DataNode tempNode;
		int tempIndexForSmallest;

		for (int i = 0; i < length - 1; i++) {
			// Initialize.
			tempNode = data[i];
			tempIndexForSmallest = i;
			for (int j = i + 1; j < length; j++) {
				if (data[j].key < tempNode.key) {
					tempNode = data[j];
					tempIndexForSmallest = j;
				} // Of if
			} // Of for j

			// Change the selected one with the current one.
			data[tempIndexForSmallest] = data[i];
			data[i] = tempNode;
		} // Of for i
	}// Of selectionSort

	public static void selectionSortTest() {
		int[] tempUnsortedKeys = { 5, 3, 6, 10, 7, 1, 9 };
		String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
		DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);

		System.out.println(tempDataArray);

		tempDataArray.selectionSort();
		System.out.println("Result\r\n" + tempDataArray);
	}// Of selectionSortTest

运行结果:

-------selectionSortTest-------
I am a data array with 7 items.
(5, if)  (3, then)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  
Result
I am a data array with 7 items.
(1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  

第 48 天: 堆排序

堆排序可能是排序算法中最难的. 用到了二叉树.
建初始堆比较费劲.
调整堆的时间复杂度为O(logn), 所以总体时间复杂度只有O(nlogn).
空间复杂度只有O(1).

新增代码如下:


	public void heapSort() {
		DataNode tempNode;
		// Step 1. Construct the initial heap.
		for (int i = length / 2 - 1; i >= 0; i--) {
			adjustHeap(i, length);
		} // Of for i
		System.out.println("The initial heap: " + this + "\r\n");

		// Step 2. Swap and reconstruct.
		for (int i = length - 1; i > 0; i--) {
			tempNode = data[0];
			data[0] = data[i];
			data[i] = tempNode;

			adjustHeap(0, i);
			System.out.println("Round " + (length - i) + ": " + this);
		} // Of for i
	}// Of heapSort


	public void adjustHeap(int paraStart, int paraLength) {
		DataNode tempNode = data[paraStart];
		int tempParent = paraStart;
		int tempKey = data[paraStart].key;

		for (int tempChild = paraStart * 2 + 1; tempChild < paraLength; tempChild = tempChild * 2 + 1) {
			// The right child is bigger.
			if (tempChild + 1 < paraLength) {
				if (data[tempChild].key < data[tempChild + 1].key) {
					tempChild++;
				} // Of if
			} // Of if

			System.out.println("The parent position is " + tempParent + " and the child is " + tempChild);
			if (tempKey < data[tempChild].key) {
				// The child is bigger.
				data[tempParent] = data[tempChild];
				System.out.println("Move " + data[tempChild].key + " to position " + tempParent);
				tempParent = tempChild;
			} else {
				break;
			} // Of if
		} // Of for tempChild

		data[tempParent] = tempNode;

		System.out.println("Adjust " + paraStart + " to " + paraLength + ": " + this);
	}// Of adjustHeap

	
	public static void heapSortTest() {
		int[] tempUnsortedKeys = { 5, 3, 6, 10, 7, 1, 9 };
		String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
		DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);

		System.out.println(tempDataArray);

		tempDataArray.heapSort();
		System.out.println("Result\r\n" + tempDataArray);
	}// Of heapSortTest

运行结果:

-------heapSortTest-------
I am a data array with 7 items.
(5, if)  (3, then)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  
The parent position is 2 and the child is 6
Move 9 to position 2
Adjust 2 to 7: I am a data array with 7 items.
(5, if)  (3, then)  (9, while)  (10, switch)  (7, case)  (1, for)  (6, else)  
The parent position is 1 and the child is 3
Move 10 to position 1
Adjust 1 to 7: I am a data array with 7 items.
(5, if)  (10, switch)  (9, while)  (3, then)  (7, case)  (1, for)  (6, else)  
The parent position is 0 and the child is 1
Move 10 to position 0
The parent position is 1 and the child is 4
Move 7 to position 1
Adjust 0 to 7: I am a data array with 7 items.
(10, switch)  (7, case)  (9, while)  (3, then)  (5, if)  (1, for)  (6, else)  
The initial heap: I am a data array with 7 items.
(10, switch)  (7, case)  (9, while)  (3, then)  (5, if)  (1, for)  (6, else)  

The parent position is 0 and the child is 2
Move 9 to position 0
The parent position is 2 and the child is 5
Adjust 0 to 6: I am a data array with 7 items.
(9, while)  (7, case)  (6, else)  (3, then)  (5, if)  (1, for)  (10, switch)  
Round 1: I am a data array with 7 items.
(9, while)  (7, case)  (6, else)  (3, then)  (5, if)  (1, for)  (10, switch)  
The parent position is 0 and the child is 1
Move 7 to position 0
The parent position is 1 and the child is 4
Move 5 to position 1
Adjust 0 to 5: I am a data array with 7 items.
(7, case)  (5, if)  (6, else)  (3, then)  (1, for)  (9, while)  (10, switch)  
Round 2: I am a data array with 7 items.
(7, case)  (5, if)  (6, else)  (3, then)  (1, for)  (9, while)  (10, switch)  
The parent position is 0 and the child is 2
Move 6 to position 0
Adjust 0 to 4: I am a data array with 7 items.
(6, else)  (5, if)  (1, for)  (3, then)  (7, case)  (9, while)  (10, switch)  
Round 3: I am a data array with 7 items.
(6, else)  (5, if)  (1, for)  (3, then)  (7, case)  (9, while)  (10, switch)  
The parent position is 0 and the child is 1
Move 5 to position 0
Adjust 0 to 3: I am a data array with 7 items.
(5, if)  (3, then)  (1, for)  (6, else)  (7, case)  (9, while)  (10, switch)  
Round 4: I am a data array with 7 items.
(5, if)  (3, then)  (1, for)  (6, else)  (7, case)  (9, while)  (10, switch)  
The parent position is 0 and the child is 1
Move 3 to position 0
Adjust 0 to 2: I am a data array with 7 items.
(3, then)  (1, for)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Round 5: I am a data array with 7 items.
(3, then)  (1, for)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Adjust 0 to 1: I am a data array with 7 items.
(1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Round 6: I am a data array with 7 items.
(1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Result
I am a data array with 7 items.
(1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  

第 49 天: 归并排序

堆排序可能是排序算法中最难的. 用到了二叉树.
建初始堆比较费劲.
调整堆的时间复杂度为 O(logn), 所以总体时间复杂度只有O(nlogn).
空间复杂度只有O(1).

新增代码如下:



	public void mergeSort() {
		// Step 1. 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.print(data[i]);
		} // Of for i
		System.out.println();

		DataNode[][] tempMatrix = new DataNode[2][length];

		// Step 2. Copy data.
		for (int i = 0; i < length; i++) {
			tempMatrix[0][i] = data[i];
		} // Of for i

		// Step 3. Merge. log n rounds
		tempRow = -1;
		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;

			tempGroups = length / (tempSize * 2);
			if (length % (tempSize * 2) != 0) {
				tempGroups++;
			} // Of if
			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];
					} // Of for i
					continue;
				} // Of if
				tempSecondEnd = tempGroupNumber * tempSize * 2 + tempSize * 2 - 1;
				if (tempSecondEnd > length - 1) {
					tempSecondEnd = length - 1;
				} // Of if

				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++;
					} // Of if
					tempNumCopied++;
				} // Of while

				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++;
				} // Of while
			} // Of for groupNumber

			System.out.println("Round " + tempRow);
			for (int i = 0; i < length; i++) {
				System.out.print(tempMatrix[tempNextRow][i] + " ");
			} // Of for j
			System.out.println();
		} // Of for tempStepSize

		data = tempMatrix[tempNextRow];
	}// Of mergeSort


	public static void mergeSortTest() {
		int[] tempUnsortedKeys = { 5, 3, 6, 10, 7, 1, 9 };
		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);
	}// Of mergeSortTest


运行结果:

-------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)  

第50天:小结

1.查找方法
1.1 顺序查找就是一个个数据挨着挨着找下去,找到目标数据就停止,方法比较笨,但是很实在
1.2 折半查找(二分法),该方法需要数据已经排好序了才行,通过比较所找的值key与举例的中间值的大小来确定接下来是往左边找还是往右边找。
参考连接 c.biancheng.net/view/189.html

2.设计一个自己的 Hash 函数和一个冲突解决机制.
(待完成)

3.排序方法

  1. 插入排序:插入排序基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入排序的基本思想是:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
  2. 选择排序:选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
  3. 冒泡排序:冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端。
  4. 快速排序:快速排序(Quicksort)是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
  5. 归并排序:归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
  6. 希尔排序:希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值