0
点赞
收藏
分享

微信扫一扫

day46

邯唐情感 2022-04-14 阅读 43

Day 46 —— Quick Sort

1. Background

今天是学习java的第46天,今天的内容是快速排序。

2. Description

快速排序的思想非常的简单,先找一个锚点,老师的代码是把每个序列的最后一个元素当作这个锚点,然后分别从头和尾*(这里的尾是锚点的前一个元素)*开始遍历。首先是从前开始遍历,此时遍历的元素必须都比锚点小。如果比锚点大,那就开始从尾遍历,从未开始的元素必须比锚点大,如果比锚点小那就和那个从前开始遍历并比锚点大的元素交换位置。

上面差不多就是快速排序的基本思想了。可以简化为:

  1. 选定Pivot锚点。
  2. 将大于Pivot锚点的元素放在后面。
  3. 将小于Pivot锚点的元素放在前面。
  4. 对所有子序列重复上面操作。

从这个简化的思想可以看出,操作差不多是重复的,只是要对不同的子对象进行操作。这是我们可以想到,使用递归无疑是非常好用的。

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
}

运行结果:

在这里插入图片描述

举报

相关推荐

0 条评论