JAVA学习—41-50天

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

顺序查找
顺序查找就是从数组的第一个元素开始,依次比较,直到找到目标数据或查找失败。
图例说明: 原始数据:int[]a={4,6,2,8,1,9,0,3}; 要查找数字:8
在这里插入图片描述

折半查找
假设查找的数组区间为 [min,max],min 代表起始索引,max 代表结束索引,T 代表需要查找的值。
第一步:确定该区间的中间位置 K;
第二步:将查找的值 T 与 array[k] 比较。若相等,查找成功返回此位置;否则确定新的查找区域,继续折半查找;
第三步:若 array[k]>T,由数组的有序性可知 array[k,k+1,……,max] 中的每个值都大于 T,故新的区间为 array[min,……,K-1],若 array[k]<T,同理可得新的查找区间为 array[k+1,……,max]。
每一次查找与中间值比较,可以确定是否查找成功,不成功的话下一次查找区间将缩小一半。

假设用变量 low 和 high 分别存储待查元素所在范围的下界和上界,变量 mid 存储区间的中间位置,即 mid = [(low + high) / 2]。
在这里插入图片描述

前提是数组中的数据是有序的。

package datastructure.search;

/**
 * Data array for searching and sorting algorithms.
 * 
 * @author hengyuzuo.
 */
public class DataArray {
	/**
	 * An inner class for data nodes. The text book usually use an int value to
	 * represent the data. I would like to use a key-value pair instead.
	 */
	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 method claimed in Object, the superclass of any class.
		 *********************
		 */
		public String toString() {
			return "(" + key + ", " + content + ") ";
		}// Of toString
	}// Of class DataNode

	/**
	 * The data array.
	 */
	DataNode[] data;

	/**
	 * The length of the 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 method claimed in Object, the superclass of any class.
	 *********************
	 */
	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

	/**
	 *********************
	 * Sequential search. Attention: It is assume that the index 0 is NOT used.
	 * 
	 * @param paraKey The given key.
	 * @return The content of the key.
	 *********************
	 */
	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.
		// This for statement is equivalent to 
		//for (i = length - 1; data[i].key != paraKey; i--);
		for (i = length - 1; data[i].key != paraKey; i--) {
			;
		}//Of for i
		return data[i].content;
	}// Of sequentialSearch

	/**
	 *********************
	 * Test the method.
	 *********************
	 */
	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

	/**
	 *********************
	 * Binary search. Attention: It is assume that keys are sorted in ascending
	 * order.
	 * 
	 * @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

	/**
	 *********************
	 * Test the method.
	 *********************
	 */
	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 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();
	}// Of main

}// Of class DataArray

第 42 天: 哈希表

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

哈希表也是一种数据结构,特点:可以根据一个key值来直接访问数据,因此查找速度快
在这里插入图片描述
哈希表的本质上也是数组

	/**
	 *********************
	 * The second constructor. For Hash code only. It is assumed that
	 * paraKeyArray.length <= paraLength.
	 * 
	 * @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. 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

	/**
	 *********************
	 * 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

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

第 43 天: 插入排序

插入排序(英语:Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

假设前面 n-1(其中 n>=2)个数已经是排好顺序的,现将第 n 个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。
按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序。
从小到大的插入排序整个过程如图示:
第一轮:从第二位置的 6 开始比较,比前面 7 小,交换位置。
在这里插入图片描述

第二轮:第三位置的 9 比前一位置的 7 大,无需交换位置。

在这里插入图片描述

第三轮:第四位置的 3 比前一位置的 9 小交换位置,依次往前比较。

在这里插入图片描述

第四轮:第五位置的 1 比前一位置的 9 小,交换位置,再依次往前比较。
在这里插入图片描述

就这样依次比较到最后一个元素。

	/**
	 *********************
	 * Insertion sort. data[0] does not store a valid data. data[0].key should
	 * be smaller than any valid key.
	 *********************
	 */
	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

	/**
	 *********************
	 * 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

第 44 天: 希尔排序

希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进。希尔排序又称缩小增量排序,因 DL.Shell 于 1959 年提出而得名。它通过比较相距一定间隔的元素来进行,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。

	/**
	 *********************
	 * 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];
					// 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

	/**
	 *********************
	 * 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

第 45 天: 冒泡排序

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

	/**
	 *********************
	 * Bubble sort.
	 *********************
	 */
	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

	/**
	 *********************
	 * 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

第 46 天: 快速排序

快速排序的本质就是把基准数大的都放在基准数的右边,把比基准数小的放在基准数的左边,这样就找到了该数据在数组中的正确位置。以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。

	/**
	 *********************
	 * Quick sort recursively.
	 * 
	 * @param paraStart The start index.
	 * @param paraEnd   The end index.
	 *********************
	 */
	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

	/**
	 *********************
	 * 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

第 47 天: 选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
在这里插入图片描述

	/**
	 *********************
	 * Selection sort. All data are valid.
	 *********************
	 */
	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

	/**
	 *********************
	 * Test the method.
	 *********************
	 */
	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

第 48 天: 堆排序

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:
在这里插入图片描述
同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子
在这里插入图片描述
该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

	/**
	 *********************
	 * Heap sort. Maybe the most difficult sorting algorithm.
	 *********************
	 */
	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

	/**
	 *********************
	 * Adjust the heap.
	 * 
	 * @param paraStart  The start of the index.
	 * @param paraLength The length of the adjusted sequence.
	 *********************
	 */
	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

	/**
	 *********************
	 * Test the method.
	 *********************
	 */
	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

第 49 天: 归并排序

归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
在这里插入图片描述

	/**
	 *********************
	 * Merge sort. Results are stored in the member variable data.
	 *********************
	 */
	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

	/**
	 *********************
	 * Test the method.
	 *********************
	 */
	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

第 50天: 总结

顺序查找
顺序查找适合于存储结构为顺序存储或链接存储的线性表。顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败。

二分查找
元素必须是有序的,如果是无序的则要先进行排序操作。也称为是折半查找,属于有序查找算法。用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表,这样递归进行,直到查找到或查找结束发现表中没有这样的结点。

插值查找
基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,差值查找也属于有序查找。对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。

哈希查找
哈希函数的规则是:通过某种转换关系,使关键字适度的分散到指定大小的的顺序结构中,越分散,则以后查找的时间复杂度越小,空间复杂度越高。哈希的思路很简单,如果所有的键都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。这是对于简单的键的情况,我们将其扩展到可以处理更加复杂的类型的键。算法流程:1)用给定的哈希函数构造哈希表;2)根据选择的冲突处理方法解决地址冲突;3)在哈希表的基础上执行哈希查找。

插入排序
计算复杂度较高,由于每个点都逐个调换,其最高复杂度于数组原顺序关系较大。
希尔排序
在插入排序的复杂度基础上较低,使得有较大跳跃的情况能够调换较快。但是因为要预估较差情况,其复杂度只能预估于插入排序在同一数量级。
冒泡排序
复杂度被浮泡必定确定一个值所限制,最大复杂度也就是循环n次。
快速排序
在冒泡排序基础上减小计算复杂度
堆排序
利用的完全二叉树的深度较低的特点,降低了复杂度。
归并排序
在使用中其实没有分这个阶段,仅需要不断两两比较即可

例子:快速的查找某一身份证

import java.util.*;

class Test {

    public static void main(String[] args) {
        HashTest people = new HashTest();

        Scanner in = new Scanner(System.in);

        for (int i = 0; i < 3; i++) // 输入个人信息,3 个测试数据
        {
            String identity = in.next();
            String name = in.next();
            int age = Integer.parseInt(in.next());
            ChinesePerson person = new ChinesePerson(identity, name, age);
            people.put(identity, person);// 以身份证为键,person 类为值
        }

        System.out.print("输入你想要查找的身份证号: ");
        String id =in.next();
        if (people.containsKey(id) == false)
            System.out.println("你要查找的信息不存在");
        else {
            ChinesePerson result = people.get(id);
            System.out.println(
                    "查找成功," + "居民身份证为:" + result.getIdCard() + ",姓名为:" + result.getName() + ",年龄为:" + result.getAge());
        }
    }
}

class HashTest {
    private ChinesePerson[] hashTable;
    private int count;

    public HashTest() // 初始化散列表
    {
        hashTable = new ChinesePerson[10000];
        count = 0;
    }

    private int HashCode(String identity) // 散列函数,除留余数法
     {
        int key = Integer.valueOf(identity.substring(9, 17)) / 10000;
        return key;
    }

    public void put(String identity, ChinesePerson person) { // 增加键和值,测试案例不做溢出判断
        int k = HashCode(identity);
        hashTable[k] = person;
        count++;
    }

    public boolean containsKey(String key) { // 判断键值是否存在
        int index = HashCode(key);
        if (index < 0 || index >= 10000 || count == 0 || hashTable[index] == null)
            return false;
        return true;
    }

    public ChinesePerson get(String key) { // 获取键对应的值
        if (containsKey(key) == false)
            throw new NullPointerException(); // 若不存在则抛出异常
        return hashTable[HashCode(key)];
    }

    public int size() { // 获取散列表对应的元素个数
        return count;
    }

}

class ChinesePerson { // 定义类存储身份信息
    private String idCard;
    private String name;
    private int age;

    public ChinesePerson(String identity, String name, int age) {
        this.idCard = identity;
        this.name = name;
        this.age = age;
    }

    public String getIdCard() {
        return this.idCard;
    }

    public void setIdCard(String identity) {
        this.idCard = identity;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值