日撸代码300行の学习笔记2:线性数据结构

日撸代码300行の学习笔记2:线性数据结构

前言

  本文是关于日撸代码300行 link的学习笔记。
  打个1折,每日代码30行。
  本文对所学习的代码根据自己的理解有所调整。
  本文的代码只是个人笔记,有些笔记比较跳跃。
  仿敲优秀代码果然是最快的编程学习方式。


day11 顺序表

  在《数据结构》中,使用“抽象数据类型”来描述不同的数据结构;在《面向对象程序设计》中,用对象来存储数据及其上的操作;它们的本质是共通的。
  对象:数据及其上操作的总和。
  从计算机的发展来看,第一阶段以操作 (函数) 为中心,比如一个计算导弹轨迹的函数,根据不同输入获得不同输出。第二阶段以数据为中心,即数据存放于数据库,使用不同的算法来处理它。第三阶段认为数据及其上的操作是统一不可分的,这就到了面向对象。
   并非程序设计必须的东西,其作用仅仅是将类进行合理的组织。但在计算机界,往往这种 可有可无 的东西才是最重要的,比如如文档、注释、编码规范。可有可无 是针对程序的运行而言,其核心是计算机;而重要是针对程序的易读性、可维护性而言,其核心是程序员。

  啰嗦一下基础知识:数组的初始化,1静态初始化:int[] a={1,2,3}。2动态初始化: int[] b=new int[2]; b[0]=1; b[2]=2;。3默认初始化。八种基本数据类型的数组的默认初始化的各元素值:
  byte[] 0;int[] 0;short[] 0;long[] 0;double[] 0.0;float[] 0.0;boolean[] false;char[] ‘\u0000’,\u0000是Unicode中的一个占位符,char[]的默认值可以理解为一个空格。
  单独提一句,对于String[],数组的每个元素是String类的对象,即每个元素是对数据的引用(数组变量肯定是引用,即对真实数据的管理者,如String[] a = new String[3],int[] b = new int[3],则a、b分别引用了String数组、int数组,但a[i]是引用了某字符串,而b[i]就是某个int),所以默认初始化不是 “”,而是 null
  再啰嗦一句,数组变量间的比较是判断是否管理着同一数组,而不是判断数组内元素值是否相等,如int[] a ={1,2,3};int[] b ={1,2,3};System.out.println(a==b);结果是false。数组变量的赋值只能赋予管理/引用权限,不能复制一个值相等的全新数组。
  因此复制数组,需要遍历“源数组”将每个元素逐一复制给“目的数组”。
  同样的,若要判断两个数组的元素是否相等,不能直接对数组变量进行“ == ”判断,而是写循环对所有元素逐个判断。

  本小节将原作者前两部分融合为一节,给出完整的顺序表。该顺序表是用数组来实现的,即给出一个固定大小的数组,用该数组的一部分来表示我们需要的线性表。该节的SequentialList类重写了toString方法方便进行测试,并给出了线性表的如下基础功能:

  • 构造初始化。包括2种,一种是默认初始化,一种是根据作为参数的给定数组完成初始化;
  • 重置线性表,将实际数组长度重置为0;
  • 查找给定元素所处的位置,找不到就返回 -1;
  • 在给定位置增加元素。如果线性表已满,或位置不在已有位置范围之内,就拒绝增加。但注意,该位置可以是在最后一个元素之后的一个;
  • 删除定定位置的元素。注意要处理给定位置不合法的情况,该位置必须是已经有数据的。
    下面给出框架:
public class SequentialList {
	private static final int MAX_LENGTH = 10;
	private int length;
	private int[] data;

	public SequentialList();
	public SequentialList(int[] paraArray);
	public void reset();
	public int locate(int paraValue);
	public boolean insert(int paraPosition, int paraValue);
	public boolean delete(int paraPosition);
	
	public String toString();
} // of class SequentialList

PS:
  method所依赖的数据既包括参数列表中给出的,也依赖于对象的成员变量。因此,面向对象所涉及的参数列表要短些。例如,locate方法就有效利用了 length 和 data 这两个成员变量。
  for ( int i = 10; i > 10; i-- ) {…}或for ( int i = length; i < paraLength; i++ ) {…}在paraLength=length时,这样的代码不会报错,也不会运行。

package dataStructure;

/**
 * Sequential list. Name and comments follow the author's style strictly.
 * 
 * @author Fan Min minfanphd@163.com.
 * @learner CatInCoffee.
 */
public class SequentialList {

	/**
	 * The maximal length of the list. It is a constant.
	 */
	private static final int MAX_LENGTH = 10;

	/**
	 * The actual length not exceeding MAX_LENGTH. Attention: length is not only the
	 * member variable of Sequential list, but also the member variable of Array. In
	 * fact, a name can be the member variable of different classes.
	 */
	private int length;

	/**
	 * The data stored in an array.
	 */
	private int[] data;

	/**
	 *********************
	 * Construct an empty sequential list.
	 *********************
	 */
	public SequentialList() {
		length = 0;
		data = new int[MAX_LENGTH];
	} // Of the first constructor

	/**
	 *********************
	 * Construct a sequential list using an array.
	 * 
	 * @param paraArray The given array. Its length should not exceed MAX_LENGTH.
	 *                  For simplicity now we do not check it.
	 *********************
	 */
	public SequentialList(int[] paraArray) {
		data = new int[MAX_LENGTH];
		length = paraArray.length;

		// Copy data.
		for (int i = 0; i < paraArray.length; i++) {
			data[i] = paraArray[i];
		} // Of for i
	} // Of the second constructor

	/**
	 *********************
	 * Override the method<toString()> claimed in Object, the superclass of any
	 * class.
	 *********************
	 */
	public String toString() {
		String resultString = "";

		if (length == 0) {
			return "empty.";
		} // Of if

		for (int i = 0; i < length - 1; i++) {
			resultString += data[i] + ", ";
		} // Of for i

		resultString += data[length - 1];

		return resultString;
	} // Of toString

	/**
	 *********************
	 * Reset to empty.
	 *********************
	 */
	public void reset() {
		length = 0;
	} // Of reset

	/**
	 *********************
	 * Locate the given value. If it appears in multiple positions, simply return
	 * the first one.
	 * 
	 * @param paraValue The given value.
	 * @return The position. -1 for not found.
	 *********************
	 */
	public int locate(int paraValue) {
		int tempPosition = -1;

		for (int i = 0; i < length; i++) {
			if (data[i] == paraValue) {
				tempPosition = i;
				break;
			} // Of if
		} // Of for i

		return tempPosition;
	} // Of locate

	/**
	 *********************
	 * Insert a value to a position. If the list is already full, do nothing.
	 * 
	 * @param paraPosition The given position.
	 * @param paraValue    The given value.
	 * @return Success or not.
	 *********************
	 */
	public boolean insert(int paraPosition, int paraValue) {
		if (length == MAX_LENGTH) {
			System.out.println("List is full.");
			return false;
		} // Of if

		if ((paraPosition < 0) || (paraPosition > length)) {
			System.out.println("The position " + paraPosition + " is out of bounds.");
			return false;
		} // Of if

		// From tail to head.
		for (int i = length; i > paraPosition; i--) {
			data[i] = data[i - 1];
		} // Of for i

		data[paraPosition] = paraValue;
		length++;

		return true;
	} // Of insert

	/**
	 *********************
	 * Delete a value at the specified position.
	 * 
	 * @param paraPosition The given position.
	 * @return Success or not.
	 *********************
	 */
	public boolean delete(int paraPosition) {
		if ((paraPosition < 0) || (paraPosition >= length)) {
			System.out.println("The position " + paraPosition + " is out of bounds.");
			return false;
		} // Of if

		// From head to tail.
		for (int i = paraPosition; i < length - 1; i++) {
			data[i] = data[i + 1];
		} // Of for i

		length--;

		return true;
	}// Of delete

	/**
	 *********************
	 * The entrance of the program.
	 * 
	 * @param args Not used now.
	 *********************
	 */
	public static void main(String[] args) {
		int[] tempArray = { 6, 7, 4, 9 };
		SequentialList tempFirstList = new SequentialList(tempArray);
		System.out.println("After being initialized, the list is: " + tempFirstList.toString());
		System.out.println("Without the toString() method, the list also is: " + tempFirstList);

		int tempValue = 4;
		int tempPosition = tempFirstList.locate(tempValue);
		System.out.println("The position of " + tempValue + " is " + tempPosition);

		tempValue = 5;
		tempPosition = tempFirstList.locate(tempValue);
		System.out.println("The position of " + tempValue + " is " + tempPosition + "\n");

		tempPosition = 2;
		tempValue = 8;
		tempFirstList.insert(tempPosition, tempValue);
		System.out.println(
				"After inserting " + tempValue + " to position " + tempPosition + ", the list is: " + tempFirstList);

		tempPosition = 8;
		tempValue = 10;
		tempFirstList.insert(tempPosition, tempValue);
		System.out.println(
				"After inserting " + tempValue + " to position " + tempPosition + ", the list is: " + tempFirstList);

		tempPosition = 3;
		tempFirstList.delete(tempPosition);
		System.out
				.println("After deleting data at position " + tempPosition + ", the list is: " + tempFirstList + "\n");

		for (int i = 0; i < 8; i++) {
			if (tempFirstList.insert(i, i)) {
				System.out.println("After inserting " + i + " to position " + i + ", the list is: " + tempFirstList);
			} else {
				System.out.println("\t So that we cannot insert "+i+" to position "+i+".");
			} // of if
		} // Of for i

		tempFirstList.reset();
		System.out.println("After the reset() method, the list is: " + tempFirstList);
	} // of main

} // of class SequentialList

结果:

After being initialized, the list is: 6, 7, 4, 9
Without the toString() method, the list also is: 6, 7, 4, 9
The position of 4 is 2
The position of 5 is -1

After inserting 8 to position 2, the list is: 6, 7, 8, 4, 9
The position 8 is out of bounds.
After inserting 10 to position 8, the list is: 6, 7, 8, 4, 9
After deleting data at position 3, the list is: 6, 7, 8, 9

After inserting 0 to position 0, the list is: 0, 6, 7, 8, 9
After inserting 1 to position 1, the list is: 0, 1, 6, 7, 8, 9
After inserting 2 to position 2, the list is: 0, 1, 2, 6, 7, 8, 9
After inserting 3 to position 3, the list is: 0, 1, 2, 3, 6, 7, 8, 9
After inserting 4 to position 4, the list is: 0, 1, 2, 3, 4, 6, 7, 8, 9
After inserting 5 to position 5, the list is: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
List is full.
	 So that we cannot insert 6 to position 6.
List is full.
	 So that we cannot insert 7 to position 7.
After the reset() method, the list is: empty.

day12 链表

  支持与顺序表相同的操作:初始化、插入、删除等。
  为节点建一个类。
  引用与指针的异同:前者只能使用;后者可以支持 p++ 危险操作。
  引用数据类型的赋值,都不会产生新的对象空间。
  链表与线性表在插入、删除时的不同:链表不再移动元素,只改变引用 (指针)。

  注意,这里的命名和java.util包的命名一样,都是LinkedList,但都能运行,也即不同包可以包含同名的类文件。这里只是关于int的单链表,更一般的是关于<AnyType>的双链表。

  注意这段代码的for循环和while的两种实现形式:

	public int indexOf(int paraValue) {
		int tempPosition = 0;

//		Node tempNodeAtPosition = header.next;
//		while (tempNodeAtPosition != tail) {
//			if (tempNodeAtPosition.data == paraValue) {
//				return tempPosition;
//			} // Of if
//			tempNodeAtPosition = tempNodeAtPosition.next;
//			tempPosition++;
//		} // Of while

		for (Node temp = header.next; temp != tail; temp = temp.next) {
			if (temp.data == paraValue) {
				return tempPosition;
			} // Of if
			tempPosition++;
		} // of for temp

		tempPosition = -1;
		return tempPosition;
	}// Of indexOf

  框架如下:

package dataStructure;

import dataStructure.LinkedList;

/**
 * Linked list. Name and comments follow the author's style strictly.
 * 
 * @author Fan Min minfanphd@163.com.
 * @learner CatInCoffee.
 */
public class LinkedList {

	private class Node {
		public int data;
		public Node next;

		public Node(int paraValue) {}// Of Node's constructor
	}// Of class Node

	private int theSize;
	private Node header;
	private Node tail;
	
	public LinkedList() {} // Of the constructor
	private void doClear() {} // of doClear
	public String toString() {} // Of toString

	public void reset() {} // Of reset
	public int indexOf(int paraValue) {}// Of indexOf
	public boolean add(int paraPosition, int paraValue) {}// Of add
	private Node getNodeBeforePosition(int paraPosition, int lower, int upper) {} // of getNodeBeforePosition
	private boolean addAfter(Node paraNode, int paraValue) {} // of addAfter
	public boolean delete(int paraPosition) {}// Of delete
	private boolean deleteAfter(Node paraNode) {} // of delete
}// Of class LinkedList

  完整代码:

package dataStructure;

import dataStructure.LinkedList;

/**
 * Linked list. Name and comments follow the author's style strictly.
 * 
 * @author Fan Min minfanphd@163.com.
 * @learner CatInCoffee.
 */
public class LinkedList {

	private class Node {
		public int data;
		public Node next;

		public Node(int paraValue) {
			data = paraValue;
			next = null;
		}// Of Node's constructor
	}// Of class Node

	private int theSize;
	private Node header;
	private Node tail;
	
	public LinkedList() {
		doClear();
	} // Of the constructor

	private void doClear() {
		header = new Node(0);
		tail = new Node(0);
		header.next = tail;
		theSize = 0;
	} // of doClear
	
	public String toString() {
		if (header.next == tail) {
			return "empty.";
		} // Of if

		String resultString = "{ ";
		Node tempNodeAtPosition = header.next;
		while (tempNodeAtPosition != tail) {
			resultString += tempNodeAtPosition.data + " ";
			tempNodeAtPosition = tempNodeAtPosition.next;
		} // Of while

		resultString += "}";
		return resultString;
	} // Of toString

	public void reset() {
		doClear();
	} // Of reset

	/**
	 *********************
	 * indexOf the given value. If it appears in multiple positions, simply return
	 * the first one.
	 * 
	 * @param paraValue the given value.
	 * @return The position. -1 for not found.
	 *********************
	 */
	public int indexOf(int paraValue) {
		int tempPosition = 0;
		Node tempNodeAtPosition = header.next;

		while (tempNodeAtPosition != tail) {
			if (tempNodeAtPosition.data == paraValue) {
				return tempPosition;
			} // Of if
			tempNodeAtPosition = tempNodeAtPosition.next;
			tempPosition++;
		} // Of while

		tempPosition = -1;
		return tempPosition;
	}// Of indexOf

	/**
	 *********************
	 * add a value at the specified position.
	 * 
	 * @param paraPosition The given position.
	 * @param paraValue    The given value.
	 * @return Success or not.
	 *********************
	 */
	public boolean add(int paraPosition, int paraValue) {
		Node tempNodeBefore = getNodeBeforePosition(paraPosition, 0, theSize);
		return addAfter(tempNodeBefore , paraValue);
	}// Of add

	private Node getNodeBeforePosition(int paraPosition, int lower, int upper) {
		if (paraPosition< lower || paraPosition > upper) {
			System.out.println("The position " + paraPosition + " is illegal.");
			return null;
		} // Of if
		
		// tempNodeBeforePosition.next is the Node at the specified position.
		Node tempNodeBeforePosition = header;
		for (int i = 0; i < paraPosition; i++) {
			tempNodeBeforePosition = tempNodeBeforePosition.next;
		} // Of for i
		return tempNodeBeforePosition;
	} // of getNodeBeforePosition
	
	/**
	 *********************
	 * Add a value after the specified Node.
	 * 
	 * @param paraNode The given Node before the Node to be added.
	 * @return Success or not.
	 *********************
	 */
	private boolean addAfter(Node paraNode, int paraValue) {
		if (paraNode == null) {
			return false;
		} else {
			Node tempNewNode = new Node(paraValue);
			tempNewNode.next = paraNode.next;
			paraNode.next = tempNewNode;
			theSize++;
			return true;
		} // of if-else
	} // of addAfter
	
	/**
	 *********************
	 * Delete a value at the specified position.
	 * 
	 * @param paraPosition The given position.
	 * @return Success or not.
	 *********************
	 */
	public boolean delete(int paraPosition) {
		if (header.next == tail) {
			System.out.println("Cannot delete element from an empty list.");
			return false;
		} // Of if

		Node tempNodeBefore = getNodeBeforePosition(paraPosition, 0, theSize-1);
		return deleteAfter(tempNodeBefore);
	}// Of delete
	
	/**
	 *********************
	 * Delete a value after the specified Node.
	 * 
	 * @param paraNode The given Node before the Node to be deleted.
	 * @return Success or not.
	 *********************
	 */
	private boolean deleteAfter(Node paraNode) {
		if (paraNode == null) {
			return false;
		} else {
			paraNode.next = paraNode.next.next;
			theSize--;
			return true;
		} // of if-else
	} // of delete
	
	public static void main(String args[]) {
		LinkedList tempFirstList = new LinkedList();
		System.out.println("Initialized, the list is: " + tempFirstList.toString());

		for (int i = 0; i < 5; i++) {
			tempFirstList.add(0, 4 - i);
		} // Of for i
		System.out.println("Add 0 1 2 3 4 successively, the list is: " + tempFirstList.toString());
		System.out.println("Add 9 to position 6 could be: " + tempFirstList.add(6, 9) + ", and the List is "
				+ tempFirstList.toString());
		System.out.println("Add 9 to position 5 could be: " + tempFirstList.add(5, 9) + ", and the List is "
				+ tempFirstList.toString());
		System.out.println();
		
		System.out.println("Delete the element at position 6 could be: " + tempFirstList.delete(6) + ", and the List is "
				+ tempFirstList.toString());
		System.out.println("Delete the element at position 0 could be: " + tempFirstList.delete(0) + ", and the List is "
				+ tempFirstList.toString());
		System.out.println("Delete the element at position 4 could be: " + tempFirstList.delete(4) + ", and the List is "
				+ tempFirstList.toString());
		System.out.println();
		
		System.out.println("Delete the element in position 0 for 5 times, the lists in sequence are: ");
		for (int i = 0; i < 5; i++) {
			tempFirstList.delete(0);
			System.out.println(tempFirstList);
		} // Of for i
	}// Of main
}// Of class LinkedList

  结果:

Initialized, the list is: empty.
Add 0 1 2 3 4 successively, the list is: { 0 1 2 3 4 }
The position 6 is illegal.
Add 9 to position 6 could be: false, and the List is { 0 1 2 3 4 }
Add 9 to position 5 could be: true, and the List is { 0 1 2 3 4 9 }

The position 6 is illegal.
Delete the element at position 6 could be: false, and the List is { 0 1 2 3 4 9 }
Delete the element at position 0 could be: true, and the List is { 1 2 3 4 9 }
Delete the element at position 4 could be: true, and the List is { 1 2 3 4 }

Delete the element in position 0 for 5 times, the lists in sequence are: 
{ 2 3 4 }
{ 3 4 }
{ 4 }
empty.
Cannot delete element from an empty list.
empty.

day13 ArrayList的学习

  本小节和下一小节参看了《数据结构与算法分析(Mark Allen Weiss 第3版)》和java.util的ArrayList和LinkedList的代码,然后用自己的理解对ArrayList和LinkedList进行梳理。
  这两节显然不是一天能看完的……
  详见:
  关于ArrayList的梳理

day14 LinkedList的学习

  详见:
  关于LinkedList的梳理

day15 栈

  这里是用数组实现的关于char的栈。自然还可以链表实现,同时更一般的是关于任意类型的栈。此外还可以添加一个peek()方法,查看顶端元素但不弹出,这样pop()方法在实现时也可以先调用peek()方法。
  基础代码如下:

package dataStructure;
/**
 * Char Stack. Name and comments follow the author's style strictly.
 * 
 * @author Fan Min minfanphd@163.com.
 * @learner CatInCoffee.
 */
public class CharStack {

	/**
	 * The depth.
	 */
	public static final int MAX_DEPTH = 10;

	/**
	 * The actual depth.
	 */
	int depth;

	/**
	 * The data
	 */
	char[] data;

	/**
	 *********************
	 * Construct an empty char stack.
	 *********************
	 */
	public CharStack() {
		depth = 0;
		data = new char[MAX_DEPTH];
	} // Of the first constructor

	/**
	 *********************
	 * Overrides the method claimed in Object, the superclass of any class.
	 *********************
	 */
	public String toString() {
		String resultString = "";
		for (int i = 0; i < depth; i++) {
			resultString += data[i];
		} // Of for i

		return resultString;
	} // Of toString

	/**
	 *********************
	 * Pushes an item onto the top of this stack.
	 * 
	 * @param paraChar The given char.
	 * @return Success or not.
	 *********************
	 */
	public boolean push(char paraChar) {
		if (depth == MAX_DEPTH) {
			System.out.print("Stack is full.");
			return false;
		} // Of if

		data[depth] = paraChar;
		depth++;

		return true;
	} // Of push

	/**
	 *********************
	 * Looks at the char at the top of this stack without removing it from the
	 * stack.
	 * 
	 * @return the object at the top of this stack.
	 *********************
	 */
	public char peek() {
		if (depth == 0) {
			System.out.print("Nothing to pop. ");
			return '\0';
		} // of if

		return data[depth - 1];
	} // of peek

	/**
	 *********************
	 * Removes the char at the top of this stack and returns that char as the value
	 * of this function.
	 * 
	 * @return the char removed from the stack.
	 *********************
	 */
	public char pop() {
		char resultChar = peek();
		if (depth > 0) {
			depth--;
		} // of if

		return resultChar;
	} // Of pop

	/**
	 *********************
	 * The entrance of the program.
	 * 
	 * @param args Not used now.
	 *********************
	 */
	public static void main(String args[]) {
		CharStack tempStack = new CharStack();

		for (char ch = 'a'; ch < 'm'; ch++) {
			tempStack.push(ch);
			System.out.println("The current stack is: " + tempStack);
		} // Of for ch
		System.out.println();

		char tempChar;
		for (int i = 0; i < 12; i++) {
			tempChar = tempStack.pop();
			System.out.print("Poped: " + tempChar);
			System.out.println(" The current stack is: " + tempStack);
		} // Of for i
	} // of main
} // of class CharStack

结果:

The current stack is: a
The current stack is: ab
The current stack is: abc
The current stack is: abcd
The current stack is: abcde
The current stack is: abcdef
The current stack is: abcdefg
The current stack is: abcdefgh
The current stack is: abcdefghi
The current stack is: abcdefghij
Stack is full.The current stack is: abcdefghij
Stack is full.The current stack is: abcdefghij

Poped: j The current stack is: abcdefghi
Poped: i The current stack is: abcdefgh
Poped: h The current stack is: abcdefg
Poped: g The current stack is: abcdef
Poped: f The current stack is: abcde
Poped: e The current stack is: abcd
Poped: d The current stack is: abc
Poped: c The current stack is: ab
Poped: b The current stack is: a
Poped: a The current stack is: 
Nothing to pop. Poped:  The current stack is: 
Nothing to pop. Poped:  The current stack is: 

day16 栈:括号匹配

  任务描述:检查一个字符串的括号是否匹配。匹配是指每个左括号有一个同类型的右括号与之对应,且左括号不可以出现在右括号右边。可以修改测试字符串,检查不同情况下的运行。
  仅在上一节的代码基础上增加了一个 bracketMatching 方法,以及 main 中的相应调拭语句。
  除了关注的括号,其它字符不起任何作用。一旦发现不匹配,就直接返回。
  栈是操作系统的核心数据结构。因为对于计算机而言,如何降低时间、空间复杂度才是王道。栈是操作系统提供的功能,有系统支持,自然快速高效,但是缺点是存储的空间不够大;而堆是关于申请内存和释放内存的函数的事,由程序自己控制,这里速度就会较栈慢些。
  代码如下,新建一个类专门测试括号匹配,通过switch case实现:

package dataStructure;

/**
 1. Check if the brackets match.
 2. 
 3. @author Fan Min minfanphd@163.com.
 4. @learner CatInCoffee.
 */
public class BracketMatching {

	/**
	 *********************
	 * Is the bracket matching?
	 * 
	 * @param paraString The given expression.
	 * @return Match or not.
	 *********************
	 */
	public static boolean bracketMatching(String paraString) {
		// Step 1. Initialize the stack through pushing a '#' at the bottom.
		CharStack tempStack = new CharStack();
		tempStack.push('#');
		char tempChar;
		char tempPopedChar;

		// Step 2. Process the string. For a string, length() is a method
		// instead of a member variable.
		for (int i = 0; i < paraString.length(); i++) {
			tempChar = paraString.charAt(i);

			switch (tempChar) {
			case '(':
			case '[':
			case '{':
				tempStack.push(tempChar);
				break;
			case ')':
				tempPopedChar = tempStack.pop();
				if (tempPopedChar != '(') {
					return false;
				} // Of if
				break;
			case ']':
				tempPopedChar = tempStack.pop();
				if (tempPopedChar != '[') {
					return false;
				} // Of if
				break;
			case '}':
				tempPopedChar = tempStack.pop();
				if (tempPopedChar != '{') {
					return false;
				} // Of if
				break;
			default:
				// Do nothing.
			}// Of switch
		} // Of for i

		tempPopedChar = tempStack.pop();
		if (tempPopedChar != '#') {
			return false;
		} // Of if

		return true;
	}// Of bracketMatching
	
	public static void main(String[] args) {
		boolean tempMatch;
		String tempExpression;

		tempExpression = "[2 + (1 - 3)] * 4";
		tempMatch = bracketMatching(tempExpression);
		System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);

		tempExpression = "(a [b}  c)";
		tempMatch = bracketMatching(tempExpression);
		System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);

		tempExpression = "(a)[b]{(c)d}";
		tempMatch = bracketMatching(tempExpression);
		System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);

		tempExpression = "{(}[)]";
		tempMatch = bracketMatching(tempExpression);
		System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);

		tempExpression = "{1024^2 / [(511 +1)^3 × 512 ]} = ?";
		tempMatch = bracketMatching(tempExpression);
		System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);
	} // of main
} // of class BracketMatching

结果:

Is the expression [2 + (1 - 3)] * 4 bracket matching? true
Is the expression (a [b}  c) bracket matching? false
Is the expression (a)[b]{(c)d} bracket matching? true
Is the expression {(}[)] bracket matching? false
Is the expression {1024^2 / [(511 +1)^3 × 512 ]} = ? bracket matching? true

day17 栈:递归

  系统会为递归建栈。例如, 累加程序, 空间复杂度是 O ( n ) O(n) O(n)(注意是空间,即储存,时间复杂度更复杂),因为只有运行到 paraN = 1 时, 才会弹栈。
递归显然不是循环推理,在数值计算上就是高中数学里的递推公式,但递归远不止用于数值的相关计算。这里只是简单的说明下递归,递归需要:

  1. 基础情形,即总有无需递归就能给出的情况。【必须】
  2. 不断推进。【必须】
  3. 假设每步递归都能运行。【基础假设,意味着我们不必追踪大量的、复杂的递归调用,默认计算机能处理这些复杂细节】
  4. 合成收益法则(compound interest rule):在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。【优秀设计原则,不满足能运行,但空间和时间消耗都会大幅提高】

  下面的例子是最浅显的递归,但并不是设计良好的递归。
  以Fibonacci数列为例,假设计算 f(5),那么需要计算 f(3)和f(4),f(4)又需要计算 f(2)和f(3),f(3)显然重复计算了。实际上里面重复计算的非常多,每条分支都需要一直分到基准情形,然后再算回来。用递归实现Fibonacci数列的时间复杂度是 O ( 1.61 8 n ) O(1.618^n) O(1.618n)(证明略。简单的说,设计算f(N)的时间为 T n T_n Tn​,那么 T n = T n − 1 + T n − 2 T_n=T_{n-1}+T_{n-2} Tn​=Tn−1​+Tn−2​,前两次为常数时间,也即相当于求Fibonacci数列,高中数学可求),可以看到时间复杂度是指数级的。

package dataStructure;

/**
 * Recursion. A method can (directly or indirectly) invoke itself. The system
 * automatically creates a stack for it.
 * 
 * @author Fan Min minfanphd@163.com.
 * @learner CatInCoffee.
 */
public class Recursion {
	/**
	 *********************
	 * Sum to N. No loop, however a stack is used.
	 * 
	 * @param paraN The given value.
	 * @return The sum.
	 *********************
	 */
	public static int sumToN(int paraN) {
		if (paraN <= 0) {
			// Basis.
			return 0;
		} // Of if

		return sumToN(paraN - 1) + paraN;
	}// Of sumToN

	/**
	 *********************
	 * Fibonacci sequence.
	 * 
	 * @param paraN The given value.
	 * @return The sum.
	 *********************
	 */
	public static int fibonacci(int paraN) {
		if (paraN <= 0) {
			// Negative values are invalid. Index 0 corresponds to the first element 0.
			return 0;
		}
		if (paraN == 1) {
			// Basis.
			return 1;
		} // Of if

		return fibonacci(paraN - 1) + fibonacci(paraN - 2);
	}// Of fibonacci

	public static void main(String[] args) {
		int tempValue = 5;
		System.out.println("0 sum to " + tempValue + " = " + sumToN(tempValue));
		tempValue = -2;
		System.out.println("0 sum to " + tempValue + " = " + sumToN(tempValue));

		for (int i = 0; i <= 5; i++) {
			System.out.println("Fibonacci " + i + ": " + fibonacci(i));
		} // Of for i
	} // of main
}// of class Recursion

结果:

0 sum to 5 = 15
0 sum to -2 = 0
Fibonacci 0: 0
Fibonacci 1: 1
Fibonacci 2: 1
Fibonacci 3: 2
Fibonacci 4: 3
Fibonacci 5: 5

day18 链队列

  入队仅操作尾部,出队仅操作头部。
  header和tail是The index to calculate the header and the tail。原因:header和tail会一直加下去,不是真实的index,而是通过%模运算得到真实的index。
  也即,data[head];应该是data[head % TOTAL_SPACE];。否则,会出现ArrayIndexOutOf-BoundsException的异常。
  换个角度,在java中,整数的a%b=a-a/b*b,是2次乘法1次加法,或许可以保持int resultValue = data[head];不变,而是在header++;后加一个判断if (header == TOTAL_SPACE) {header = 0;},即通过一个额外的判断来实现循环,取消掉所有的%模运算,在tail部分同理,不过注意toString的实现需要调整代码(header可能大于tail)。当然,节约的计算量微乎其微,且没有模运算看起来巧妙,不过代码的可阅读性增强了,同时有意识地控制了模运算的次数。

package dataStructure;

/** about class author ...
 */
public class LinkedQueue {

	private static class Node {
		int data;
		Node next;
		
		public Node(int paraValue) {
			data = paraValue;
			next = null;
		}// Of the constructor
	}// Of class Node

	Node header;
	Node tail;

	public LinkedQueue() {
		doConstruct();
	}// Of the first constructor

	private void doConstruct() {
		header = new Node(-1);
		tail = header;
	} // of doConstruct()
	
	public void enqueue(int paraValue) {		
		Node tempNode = new Node(paraValue);
		tail.next = tempNode;
		tail = tempNode;
	}// Of enqueue

	public int dequeue() {
//		if (header.next == null) {		
		if (header == tail) {
			System.out.println("No element in the queue");
			return -1;
		} // Of if

		int resultValue = header.next.data;
		header.next = header.next.next;
		
		if (header.next == null) {
			doConstruct();
		} // of if
		
		return resultValue;
	}// Of dequeue

	public String toString() {
		String resultString = "{ ";

		if (header == tail) {
//		if (header.next == null) {
			return "empty";
		} // Of if

//		Node tempNode = header.next;
//		while (tempNode != null) {
//			resultString += tempNode.data + ", ";
//			tempNode = tempNode.next;
//		} // Of while

		for (Node tempNode = header.next; tempNode != null; tempNode = tempNode.next) {
			resultString += tempNode.data + " ";
		} // of for tempNode

		resultString += "}";
		return resultString;
	}// Of toString

	public static void main(String args[]) {
		LinkedQueue tempQueue = new LinkedQueue();
		System.out.println("Initialized, the list is: " + tempQueue.toString());

		for (int i = 0; i < 5; i++) {
			tempQueue.enqueue(i + 1);
		} // Of for i
		System.out.println("Enqueued 1 to 5 successively, the queue is: " + tempQueue);
		tempQueue.dequeue();
		System.out.println("Dequeued, the queue is: " + tempQueue);
		System.out.println();

		int tempValue;
		for (int i = 0; i < 5; i++) {
			tempValue = tempQueue.dequeue();
			System.out.println("Looped delete " + tempValue + ", the new queue is: " + tempQueue);
		} // Of for i
		
		for (int i = 1; i < 4; i++) {
			tempQueue.enqueue(i*10);
			System.out.println("Enqueued" + i*10 + ", the queue is: " + tempQueue);
		} // Of for i
	} // Of main
} // Of class LinkedQueue

结果:

Initialized, the list is: empty
Enqueued 1 to 5 successively, the queue is: { 1 2 3 4 5 }
Dequeued, the queue is: { 2 3 4 5 }

Looped delete 2, the new queue is: { 3 4 5 }
Looped delete 3, the new queue is: { 4 5 }
Looped delete 4, the new queue is: { 5 }
Looped delete 5, the new queue is: empty
No element in the queue
Looped delete -1, the new queue is: empty
Enqueued10, the queue is: { 10 }
Enqueued20, the queue is: { 10 20 }
Enqueued30, the queue is: { 10 20 30 }

day19 循环队列

  核心是利用求余运算%完成达成循环的判断。
  保留一个空节点,用于判断。传统方法是header、tail一直增加,然后模运算到相应节点,也可以加一个判断来控制代码中的模运算。

  后面将这里的代码改写为关于任意类型的泛型类CircleQueue<AnyType>,并应用在字符队列上。

package dataStructure;

/**
 * Circle int queue.
 * 
 * @author Fan Min minfanphd@163.com.
 * @learner CatInCoffee.
 */
public class CircleIntQueue {

	/**
	 * The total space. One space should never be used.
	 */
	public static final int TOTAL_SPACE = 10;

	int[] data;

	/**
	 * The index of the header and the tail.
	 */
	int header;
	int tail;

	/**
	 ******************* 
	 * The constructor
	 ******************* 
	 */
	public CircleIntQueue() {
		data = new int[TOTAL_SPACE];
		header = 0;
		tail = 0;
	} // Of the constructor

	/**
	 *********************
	 * Enqueue.
	 * 
	 * @param paraValue The value of the new node.
	 *********************
	 */
	public void enqueue(int paraValue) {
		if ((tail + 1) % TOTAL_SPACE == header) {
			System.out.println("The queue is full.");
			return;
		} // Of if

		data[tail] = paraValue;
		tail++;
		if (tail == TOTAL_SPACE) {
			tail = 0;
		} // of if
	} // Of enqueue

	/**
	 *********************
	 * Dequeue.
	 * 
	 * @return The value at the header.
	 *********************
	 */
	public int dequeue() {
		if (header == tail) {
			System.out.println("There is no element in the queue.");
			return -1;
		} // Of if

		int resultValue = data[header];

		header++;
		if (header == TOTAL_SPACE) {
			header = 0;
		} // of if

		return resultValue;
	} // Of dequeue

	/**
	 *********************
	 * Overrides the method claimed in Object, the superclass of any class.
	 *********************
	 */
	public String toString() {
		String resultString = "{ ";

		if (header == tail) {
			return "empty.";
		} else if (header < tail) {
			for (int i = header; i < tail; i++) {
				resultString += data[i] + " ";
			} // Of for i
		} else {
			for (int i = header; i < TOTAL_SPACE; i++) {
				resultString += data[i] + " ";
			} // Of for i
			for (int j = 0; j < tail; j++) {
				resultString += data[j] + " ";
			} // Of for j
//			for (int k = header; k < tail + TOTAL_SPACE; k++) {
//				resultString += data[k % TOTAL_SPACE] + " ";
//			} // Of for k
		} // of if-elseIf-if

		resultString += "}";
		return resultString;
	} // Of toString

	/**
	 *********************
	 * The entrance of the program.
	 * 
	 * @param args Not used now.
	 *********************
	 */
	public static void main(String args[]) {
		CircleIntQueue tempQueue = new CircleIntQueue();
		System.out.println("Initialized, the list is: " + tempQueue);

		for (int i = 0; i < 5; i++) {
			tempQueue.enqueue(i);
		} // Of for i
		System.out.println("Enqueue, the queue is: " + tempQueue);

		int tempValue = tempQueue.dequeue();
		System.out.println("Dequeue " + tempValue + ", the queue is: " + tempQueue);
		tempValue = tempQueue.dequeue();
		System.out.println("Dequeue " + tempValue + ", the queue is: " + tempQueue);
		System.out.println();

		for (int i = 0; i < 7; i++) {
			tempQueue.enqueue(i + 5);
			System.out.println("Enqueue, the queue is: " + tempQueue);
		} // Of for i
		System.out.println();

		for (int i = 0; i < 9; i++) {
			tempQueue.dequeue();
		} // Of for i
		System.out.println("Dequeue 9 elements , and the queue is: " + tempQueue);

		System.out.println();
		tempQueue.dequeue();
		System.out.println("Dequeue, the queue is: " + tempQueue);
		tempQueue.enqueue(10);
		System.out.println("Enqueue, the queue is: " + tempQueue);
	} // Of main
} // Of CircleIntQueue

结果:

Initialized, the list is: empty.
Enqueue, the queue is: { 0 1 2 3 4 }
Dequeue 0, the queue is: { 1 2 3 4 }
Dequeue 1, the queue is: { 2 3 4 }

Enqueue, the queue is: { 2 3 4 5 }
Enqueue, the queue is: { 2 3 4 5 6 }
Enqueue, the queue is: { 2 3 4 5 6 7 }
Enqueue, the queue is: { 2 3 4 5 6 7 8 }
Enqueue, the queue is: { 2 3 4 5 6 7 8 9 }
Enqueue, the queue is: { 2 3 4 5 6 7 8 9 10 }
The queue is full.
Enqueue, the queue is: { 2 3 4 5 6 7 8 9 10 }

Dequeue 9 elements , and the queue is: empty.

There is no element in the queue.
Dequeue, the queue is: empty.
Enqueue, the queue is: { 10 }

  改写为泛型类CircleQueue,并用字符队列来测试。

package dataStructure;

public class CircleQueue<T> {
	public static final int TOTAL_SPACE = 6;

	private T[] data;


//	The index of the header and the tail.
	private int header;
	private int tail;

	public CircleQueue() {
		data = (T[]) (new Object[TOTAL_SPACE]);
		header = 0;
		tail = 0;
	} // Of the constructor

	public void enqueue(T paraValue) {
		if ((tail + 1) % TOTAL_SPACE == header) {
			System.out.println("The queue is full.");
			return;
		} // Of if

		data[tail] = paraValue;
		tail++;
		if (tail == TOTAL_SPACE) {
			tail = 0;
		} // of if
	} // Of enqueue

	public T dequeue() {
		if (header == tail) {
			System.out.println("There is no element in the queue.");
			return null;
		} // Of if

		T resultValue = data[header];
		header++;
		if (header == TOTAL_SPACE) {
			header = 0;
		} // of if

		return resultValue;
	} // Of dequeue

	public String toString() {
		String resultString = "{ ";

		if (header == tail) {
			return "empty.";
		} else if (header < tail) {
			for (int i = header; i < tail; i++) {
				resultString += data[i] + " ";
			} // Of for i
		} else {
			for (int i = header; i < TOTAL_SPACE; i++) {
				resultString += data[i] + " ";
			} // Of for i
			for (int j = 0; j < tail; j++) {
				resultString += data[j] + " ";
			} // Of for j
//			for (int k = header; k < tail + TOTAL_SPACE; k++) {
//				resultString += data[k % TOTAL_SPACE] + " ";
//			} // Of for k
		} // of if-elseIf-if

		resultString += "}";
		return resultString;
	} // Of toString

	public static void main(String args[]) {
		CircleQueue<Character> tempQueue = new CircleQueue<>();
		System.out.println("Initialized, the TOTAL_SPACE is: " + TOTAL_SPACE + " , and the list is: " + tempQueue);

		for (char i = '0'; i < '4'; i++) {
			tempQueue.enqueue(i);
		} // Of for i
		System.out.println("Enqueue, the queue is: " + tempQueue);

		Character tempValue = tempQueue.dequeue();
		System.out.println("Dequeue " + tempValue + ", the queue is: " + tempQueue);

		for (char i = 'a'; i < 'd'; i++) {
			tempQueue.enqueue(i);
			System.out.println("Enqueue, the queue is: " + tempQueue);
		} // Of for i
		System.out.println();

		for (int i = 0; i < 6; i++) {
			tempValue = tempQueue.dequeue();
			System.out.println("Dequeue " + tempValue + ", the queue is: " + tempQueue);
		} // Of for i
		System.out.println();

		for (char i = 'A'; i <= 'F'; i++) {
			tempQueue.enqueue(i);
			System.out.println("Enqueue, the queue is: " + tempQueue);
		} // Of for i
	} // Of main
} // Of CircleQueue<T>

结果:

Initialized, the TOTAL_SPACE is: 6 , and the list is: empty.
Enqueue, the queue is: { 0 1 2 3 }
Dequeue 0, the queue is: { 1 2 3 }
Enqueue, the queue is: { 1 2 3 a }
Enqueue, the queue is: { 1 2 3 a b }
The queue is full.
Enqueue, the queue is: { 1 2 3 a b }

Dequeue 1, the queue is: { 2 3 a b }
Dequeue 2, the queue is: { 3 a b }
Dequeue 3, the queue is: { a b }
Dequeue a, the queue is: { b }
Dequeue b, the queue is: empty.
There is no element in the queue.
Dequeue null, the queue is: empty.

Enqueue, the queue is: { A }
Enqueue, the queue is: { A B }
Enqueue, the queue is: { A B C }
Enqueue, the queue is: { A B C D }
Enqueue, the queue is: { A B C D E }
The queue is full.
Enqueue, the queue is: { A B C D E }

day20 字符串匹配

  打印引号方式:\"

package dataStructure;

/** about class author ...
 */
public class MyString {
	public static final int MAX_LENGTH = 10;

	private int length;
	private char[] data;

	public MyString() {
		doConstruct();
	} // Of the first constructor

	private void doConstruct() {
		length = 0;
		data = new char[MAX_LENGTH];
	} // of doConstruct()

	public MyString(String paraString) {
		if (paraString.length() > MAX_LENGTH) {
			System.out.println("The String <" + paraString + "> cannot be initialized.");
			doConstruct();
			return;
		} // of if

		data = new char[MAX_LENGTH];
		length = paraString.length();

		for (int i = 0; i < length; i++) {
			data[i] = paraString.charAt(i);
		} // Of for i
	} // Of the second constructor

	public String toString() {
		String resultString = "";

		for (int i = 0; i < length; i++) {
			resultString += data[i];
		} // Of for i

		return resultString;
	} // Of toString

	/**
	 *********************
	 * Locate the position of a substring.
	 * 
	 * @param paraString The given substring.
	 * @return The first position. -1 for no matching.
	 *********************
	 */
	public int locate(MyString paraMyString) {
		boolean tempMatch = false;

		for (int i = 0; i < length - paraMyString.length + 1; i++) {
			// Initialize.
			tempMatch = true;
			for (int j = 0; j < paraMyString.length; j++) {
				if (data[i + j] != paraMyString.data[j]) {
					tempMatch = false;
					break;
				} // Of if
			} // Of for j

			if (tempMatch) {
				return i;
			} // Of if
		} // Of for i

		return -1;
	} // Of locate

	/**
	 *********************
	 * Get a substring
	 * 
	 * @param paraString        The given substring.
	 * @param paraStartPosition The start position in the original string.
	 * @param paraLength        The length of the new string.
	 * @return The first position. -1 for no matching.
	 *********************
	 */
	public MyString substring(int paraStartPosition, int paraLength) {
		if (paraStartPosition + paraLength > length) {
			System.out.print("The bound is exceeded. \t");
			return null;
		} // Of if

		MyString resultMyString = new MyString();
		resultMyString.length = paraLength;
		for (int i = 0; i < paraLength; i++) {
			resultMyString.data[i] = data[paraStartPosition + i];
		} // Of for i

		return resultMyString;
	} // Of substring

	public static void main(String args[]) {
		MyString tempFirstString = new MyString("I like ik....");
		tempFirstString = new MyString("I like iki");
		MyString tempSecondString = new MyString("ik");
		int tempPosition = tempFirstString.locate(tempSecondString);
		System.out.println(
				"The position of \"" + tempSecondString + "\" in \"" + tempFirstString + "\" is: " + tempPosition);

		MyString tempThirdString = new MyString("ki");
		tempPosition = tempFirstString.locate(tempThirdString);
		System.out.println(
				"The position of \"" + tempThirdString + "\" in \"" + tempFirstString + "\" is: " + tempPosition);

		tempThirdString = new MyString("love");
		tempPosition = tempFirstString.locate(tempThirdString);
		System.out.println(
				"The position of \"" + tempThirdString + "\" in \"" + tempFirstString + "\" is: " + tempPosition);
		
		tempThirdString = tempFirstString.substring(1, 2);
		System.out.println("The substring is: \"" + tempThirdString + "\"");

		tempThirdString = tempFirstString.substring(5, 5);
		System.out.println("The substring is: \"" + tempThirdString + "\"");

		tempThirdString = tempFirstString.substring(5, 6);
		System.out.println("The substring is: \"" + tempThirdString + "\"");
	} // Of main

} // Of class MyString

结果:

The String <I like ik....> cannot be initialized.
The position of "ik" in "I like iki" is: 3
The position of "ki" in "I like iki" is: 8
The position of "love" in "I like iki" is: -1
The substring is: " l"
The substring is: "e iki"
The bound is exceeded. 	The substring is: "null"
上一篇:重新整理 mysql 基础篇————— mysql 事务[三]


下一篇:重新整理 mysql 基础篇————— mysql 事务[三]