2021-05-31

第十一天:顺序表(一)

此处为闵老师发布学习内容理论知识,今日对理论概念进行了一定了解,在《数据结构》中, 使用“抽象数据类型”来描述不同的数据结构. 在《面向对象程序设计》中, 用对象来存储数据及其上的操作. 我认为, 它们的本质都是相同的.
11.1 对象: 数据及其上操作的总和. 例如, 我是一个对象, 具有身高、体重、年龄、跑步速度等数据; 同时,我具有吃饭、睡觉、送快递等功能. 从计算机的发展来看, 第一阶段以操作 (函数) 为中心, 一个计算导弹轨迹的函数, 根据不同输入获得不同输出. 第二阶段以数据为中心, 即数据存放于数据库, 使用不同的算法来处理它. 第三阶段认为数据及其上的操作是统一不可分的, 这就到了面向对象.
11.2 类. 前面已经使用过 int i; 这类代码, int 就是类型, i 是一个具体的整数变量. 同理, 对象就是属于某种类的变量. 也可以用集合的方式来理解: 类是集合, 对象是其中的元素; int 是指所有整数的集合, i 是其中的一个元素.
11.3 包. 包并非程序设计必须的东西, 其作用仅仅是将类进行合理的组织. 但是, 在计算机界, 往往这种可有可无的东西才是最重要的. 如文档、注释、编码规范. 可有可无是针对程序的运行而言, 其核心是计算机; 而重要是针对程序的易读性、可维护性而言, 其核心是程序员.
11.4 常量用 final 修饰. 这里故意把 MAX_LENGTH 设置得比较少, 方便调拭后面的越界检查代码.
11.5 用 new 生成新的对象.
11.6 有一个成员变量叫做 length. 程序里还有用 length 表示一个整数数组的长度. 实际上, 同一个变量名可以被不同的类所使用, 例如: 人有体重, 西瓜也有重量. 由于限定了不同的类、不同的对象, 它们之间就不会有冲突. 张三的体重、李四的体重,有关联才奇怪了. 这段描述写出来怪怪的, 明明现实生活中就是如此. 但这也正是体现了面向对象的特点: 比面向过程的程序设计更贴合我们的人类认知, 也就更远离机器底层.
11.7 toString 这个方法很特殊, 它覆盖了 Object 类的相应方法. 可以看到, 在 println 里面使用 tempFirstList 里, 由于是用另一个字符串与其相加, 系统会自动调用 tempFirstList.toString().

package 顺序表;
/**
 * Sequential list.
 * 
 * @author Fan Min minfanphd@163.com.
 */
public class SequentialList {

	/**
	 * The maximal length of the list. It is a constant.
	 */
	public 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.
	 */
	int length;

	/**
	 * The data stored in an array.
	 */
	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

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

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

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

}// Of class SequentialList

顺序表:通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表,将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。

运行结果:

第十二天:顺序表2

今天的代码直接在昨天的基础上增加. 只贴出新的部分.
12.1 查找给定元素所处的位置. 找不到就返回 -1.
12.2 在给定位置增加元素. 如果线性表已满, 或位置不在已有位置范围之内, 就拒绝增加. 该位置可以是在最后一个元素之后一个.
12.3 删除定定位置的元素. 要处理给定位置不合法的情况. 该位置必须是已经有数据的.
12.4 函数 要求同样的输入参数获得同样的输出结果, 但 方法 所依赖的数据既包括参数列表中给出的,也依赖于对象的成员变量. 因此, 面向对象所涉及的参数列表要短些. 例如, locate 方法就有效利用了 length 和 data 这两个成员变量.
 

package helloworld;

public class SequentialList {
	public static final int MAX_LENGTH = 10; //顺序表的最大长度
	int length;
	int[] data;
	public  SequentialList() {
		length=0;
		data=new int [MAX_LENGTH];
	}//SequentialList 1
	
	public SequentialList(int[] paraArray) {
		data = new int[MAX_LENGTH];
		length=paraArray.length;
		//复制数据
		for (int i = 0; i < paraArray.length; i++) {
			data[i] = paraArray[i];
		}//for
	}//SequentialList 2
	
	public String toString() {
		String resultString = "";
		if (length == 0) {
			return "empty";
		}//if
		for (int i = 0; i < length - 1; i++) {
			resultString += data[i] + ", ";
		}//for
		
		resultString += data[length - 1];
		return resultString;
	}//toString
	
	public void reset() {
		length=0;
	}//reset
	
	public static void main(String args[]) {
		int[] tempArray= {1,4,6,9};
		SequentialList tempFirstList = new SequentialList(tempArray);
		System.out.println("Initialized, the list is: " + tempFirstList.toString());
		System.out.println("Again, the list 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);
		
		tempPosition = 2;
		tempValue = 5;
		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);
		
		for(int i = 0; i < 8; i ++) {
			tempFirstList.insert(i, i);
			System.out.println("After inserting " + i + " to position " + i
	   				+ ", the list is: " + tempFirstList);
			
		}//i
		
		tempFirstList.reset();
		System.out.println("After reset, the list is: " + tempFirstList);

	}//main
	
	 public int locate(int paraValue) {
		 int tempPosition = -1;
		 for (int i = 0; i < length; i++) {
			 if(data[i]==paraValue) {
				 tempPosition = i;
				 break;
			 }//if
		 }//i
		 return tempPosition;
	 }//locate
	 
	 public boolean insert(int paraPosition, int paraValue) {
		 if(length==MAX_LENGTH) {
			 System.out.println("List full.");
			 return false;
		 }//if
		 
		 if ((paraPosition < 0) || (paraPosition > length)) {
			 System.out.println("The position " + paraPosition + " is out of bounds.");
			 return false;
		 }//if
		 
		 //从尾到头
			for (int i = length; i > paraPosition; i--) {
				data[i] = data[i - 1];
			}//i
			
			data[paraPosition] = paraValue;
			length++;
			return true;
	 }//insert
	 
	 //删除数据
	 public boolean delete(int paraPosition) {
		 if ((paraPosition < 0) || (paraPosition >= length)) {
			 System.out.println("The position " + paraPosition + " is out of bounds.");
			 return false;			 
		 }//if
		 //从头到尾
		 
		 for (int i = paraPosition; i < length - 1; i++) {
			 data[i] = data[i + 1];
		 }//i
		 length--;
		 return true;
	 }//delete
	 
	 

}

输出结果:

第十三天:链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点组成,一般情况下每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

下面是闵老师分节点学习内容:

13.1 支持与顺序表相同的操作: 初始化、插入、删除等.
13.2 为节点建一个类.
13.3 引用与指针的异同. 前者只能使用; 后者可以支持 p ++ 危险操作.
13.4 引用数据类型的赋值, 都不会产生新的对象空间.
13.5 链表与线性表在插入、删除时的不同: 前者不移动元素, 只改变引用 (指针).
13.6 今天的代码稍微多一点, 不过有昨天的铺垫, 还好.
13.7 第一个版本中, 128 和 164 行的 if 语句中都少了一个 .next, 导致对最后一个位置的检查出错 (空指针异常). 本 bug 由许嘉欣同学找到并修复.

package datastructure;

/**
 * Linked list.
 * 
 * @author Fan Min minfanphd@163.com.
 */

public class LinkedList {

	/**
	 * An inner class.
	 */
	class Node {
		/**
		 * The data.
		 */
		int data;

		/**
		 * The reference to the next node.
		 */
		Node next;

		/**
		 ******************* 
		 * The constructor
		 * 
		 * @param paraValue
		 *            The data.
		 ******************* 
		 */
		public Node(int paraValue) {
			data = paraValue;
			next = null;
		}// Of the constructor
	}// Of class Node

	/**
	 * The header node. The data is never used.
	 */
	Node header;

	/**
	 *********************
	 * Construct an empty sequential list.
	 *********************
	 */
	public LinkedList() {
		header = new Node(0);
		//header.next = null; //Redundant
	}// Of the first constructor

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

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

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

		return resultString;
	}// Of toString

	/**
	 *********************
	 * Reset to empty. Free the space through garbage collection.
	 *********************
	 */
	public void reset() {
		header.next = null;
	}// 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;

		Node tempNode = header.next;
		int tempCurrentPosition = 0;
		while (tempNode != null) {
			if (tempNode.data == paraValue) {
				tempPosition = tempCurrentPosition;
				break;
			} // Of if

			tempNode = tempNode.next;
			tempCurrentPosition++;
		} // Of while

		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) {
		Node tempNode = header;
		Node tempNewNode;

		for (int i = 0; i < paraPosition; i++) {
			if (tempNode.next == null) {
				System.out.println("The position " + paraPosition + " is illegal.");
				return false;
			} // Of if

			tempNode = tempNode.next;
		} // Of for i

		// Construct a new node.
		tempNewNode = new Node(paraValue);

		// Now link them.
		tempNewNode.next = tempNode.next;
		tempNode.next = tempNewNode;

		return true;
	}// Of insert

	/**
	 *********************
	 * Delete a value at a position.
	 * 
	 * @param paraPosition
	 *            The given position.
	 * @return Success or not.
	 *********************
	 */
	public boolean delete(int paraPosition) {
		if (header.next == null) {
			System.out.println("Cannot delete element from an empty list.");
			return false;
		} // Of if

		Node tempNode = header;

		for (int i = 0; i < paraPosition; i++) {
			if (tempNode.next.next == null) {
				System.out.println("The position " + paraPosition + " is illegal.");
				return false;
			} // Of if

			tempNode = tempNode.next;
		} // Of for i

		tempNode.next = tempNode.next.next;

		return true;
	}// Of delete

	/**
	 *********************
	 * The entrance of the program.
	 * 
	 * @param args
	 *            Not used now.
	 *********************
	 */
	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.insert(0, i);
		} // Of for i
		System.out.println("Inserted, the list is: " + tempFirstList.toString());

		tempFirstList.insert(6, 9);

		tempFirstList.delete(4);

		tempFirstList.delete(2);
		System.out.println("Deleted, the list is: " + tempFirstList.toString());

		tempFirstList.delete(0);
		System.out.println("Deleted, the list is: " + tempFirstList.toString());

		for (int i = 0; i < 5; i++) {
			tempFirstList.delete(0);
			System.out.println("Looped delete, the list is: " + tempFirstList.toString());
		} // Of for i
	}// Of main
}// Of class LinkedList

运行结果如下:

第十三天:栈

  栈是一种用于存储数据的简单数据结构,有点类似链表或者顺序表(统称线性表),栈与线性表的最大区别是数据的存取的操作,我们可以这样认为栈(Stack)是一种特殊的线性表,其插入和删除操作只允许在线性表的一端进行,一般而言,把允许操作的一端称为栈顶(Top),不可操作的一端称为栈底(Bottom),同时把插入元素的操作称为入栈(Push),删除元素的操作称为出栈(Pop)。若栈中没有任何元素,则称为空栈
 

package datastructure;

/**
 * Char stack. I do not use Stack because it is already defined in Java.
 * 
 * @author Fan Min minfanphd@163.com.
 */
public class CharStack {
	/**
	 * The depth.
	 */
	public static final int MAX_DEPTH = 10;

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

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

	/**
	 *********************
	 * Construct an empty sequential list.
	 *********************
	 */
	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

	/**
	 *********************
	 * Push an element.
	 * 
	 * @param paraChar
	 *            The given char.
	 * @return Success or not.
	 *********************
	 */
	public boolean push(char paraChar) {
		if (depth == MAX_DEPTH) {
			System.out.println("Stack full.");
			return false;
		} // Of if

		data[depth] = paraChar;
		depth++;

		return true;
	}// Of push

	/**
	 *********************
	 * Push an element.
	 * 
	 * @param paraChar
	 *            The given char.
	 * @return Success or not.
	 *********************
	 */
	public char pop() {
		if (depth == 0) {
			System.out.println("Nothing to pop.");
			return '\0';
		} // of pop

		char resultChar = data[depth - 1];
		depth--;

		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 i

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


运行结果:

第十五天:栈的应用

任务描述: 检查一个字符串的括号是否匹配. 所谓匹配, 是指每个左括号有相应的一个右括号与之对应, 且左括号不可以出现在右括号右边. 可以修改测试字符串, 检查不同情况下的运行.
1、仅在栈的代码基础上增加了一个 bracketMatching 方法, 以及 main 中的相应调试语句.
2、一旦发现不匹配, 直接返回false.
3、引用Scanner输入字符串来判断.
 

public class CharStack2 {
 
	public static final int MAX_DEPTH = 10;
	 
	int depth;
 
	char[] data;
 
 
	public CharStack() {
		depth = 0;
		data = new char[MAX_DEPTH];
	}// Of the first constructor
	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, 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
 
		tempPopedChar = tempStack.pop();
		if (tempPopedChar != '#') {
			return false;
		} // Of if
 
		return true;
	}// Of bracketMatching
 
	public String toString() {
		String resultString = "";
		for (int i = 0; i < depth; i++) {
			resultString += data[i];
		} // Of for i
 
		return resultString;
	}// Of toString
 
	public boolean push(char paraChar) {
		if (depth == MAX_DEPTH) {
			System.out.println("Stack full.");
			return false;
		} // Of if
 
		data[depth] = paraChar;
		depth++;
 
		return true;
	}// Of push
 
 
	public char pop() {
		if (depth == 0) {
			System.out.println("Nothing to pop.");
			return '\0';
		} // of pop
 
		char resultChar = data[depth - 1];
		depth--;
 
		return resultChar;
	}// Of pop
 
 
	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 i
 
		char tempChar;
		for (int i = 0; i < 12; i++) {
			tempChar = tempStack.pop();
			System.out.println("Poped: " + tempChar);
			System.out.println("The current stack is: " + tempStack);
		} // Of for i
 
		boolean tempMatch;
		String tempExpression = "[2 + (1 - 3)] * 4";
		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 = "()()(())";
		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 = ")(";
		tempMatch = bracketMatching(tempExpression);
		System.out
				.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);
	}// Of main
}

运行结果:

第十六天:递归

递归就是:A方法调用A方法,自己调用自己
递归结构:
递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
递归尾:什么时候需要调用自身方法。
 

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.
 */
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
	
	/**
	 *********************
	 * The entrance of the program.
	 * 
	 * @param args
	 *            Not used now.
	 *********************
	 */
	public static void main(String args[]) {
		int tempValue = 5;
		System.out.println("0 sum to " + tempValue + " = " + sumToN(tempValue));
		tempValue = -1;
		System.out.println("0 sum to " + tempValue + " = " + sumToN(tempValue));
		
		for(int i = 0; i < 10; i ++) {
			System.out.println("Fibonacci " + i + ": " + fibonacci(i));
		}//Of for i
	}// Of main
}// Of class Recursion

运行结果:

第十七天:链队列

 链式队列的概念
1.1 链式队列的定义
链式队列是基于单链表的存储表示实现的队列。
1.2 链式队列中各元素的逻辑及存储关系
链式队列可以采用单链表作为其存储表示,因此,可以在链式队列的声明中用单链表定义它的存储空间。
链式队列的队头指针指向单链表的第一个结点,队尾指针指向单链表的最后一个结点。
注:链式队列的队头元素存放在单链表的第一个结点内,若要从队列中退出一个元素,必须从单链表中删去第一个结点,而存放着新元素的结点应插在队列的队尾,即单链表的最后一个结点后面,这个新节点将成为新的队尾。
1.3 链式队列的特点
用单链表表示的链式队列特别适合于数据元素变动比较大的情况,而且不存在队列满而产生溢出的情况。
若程序中要使用多个队列,与多个栈的情形一样,用链接表示不仅能够提高效率,还可以达到共享存储空间的目的。
使用链式队列不会出现存储分配不合理的问题,也不需要进行存储的移动,
 

package datastructure.queue;

/**
 * Linked list.
 * 
 * @author Fan Min minfanphd@163.com.
 */
public class LinkedQueue {

	/**
	 * An inner class.
	 */
	class Node {
		/**
		 * The data.
		 */
		int data;

		/**
		 * The reference to the next node.
		 */
		Node next;

		/**
		 ******************* 
		 * The constructor
		 * 
		 * @param paraValue
		 *            The data.
		 ******************* 
		 */
		public Node(int paraValue) {
			data = paraValue;
			next = null;
		}// Of the constructor
	}// Of class Node

	/**
	 * The header of the queue.
	 */
	Node header;

	/**
	 * The tail of the queue.
	 */
	Node tail;

	/**
	 *********************
	 * Construct an empty sequential list.
	 *********************
	 */
	public LinkedQueue() {
		header = new Node(-1);
		header.next = null;

		tail = header;
	}// Of the first constructor

	/**
	 *********************
	 * Enqueue.
	 * 
	 * @param paraValue
	 *            The value of the new node.
	 *********************
	 */
	public void enqueue(int paraValue) {
		Node tempNode = new Node(paraValue);
		tail.next = tempNode;
		tail = tempNode;
	}// Of enqueue

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

		int resultValue = header.next.data;

		header.next = header.next.next;

		return resultValue;
	}// Of dequeue

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

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

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

		return resultString;
	}// Of toString

	/**
	 *********************
	 * The entrance of the program.
	 * 
	 * @param args
	 *            Not used now.
	 *********************
	 */
	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("Enqueue, the queue is: " + tempQueue.toString());

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

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

运行结果:

第十八天:循环队列

循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列,循环队列可以克服“假溢出”问题。

package datastructure.queue;

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

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

	/**
	 * The data.
	 */
	int[] data;

	/**
	 * The index of the head.
	 */
	int head;

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

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

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

		data[tail % TOTAL_SPACE] = paraValue;
		tail++;
	}// Of enqueue

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

		int resultValue = data[head];

		head++;

		return resultValue;
	}// Of dequeue

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

		if (head == tail) {
			return "empty";
		} // Of if

		for (int i = head; i < tail; i++) {
			resultString += data[i % TOTAL_SPACE] + ", ";
		} // Of for i

		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.toString());

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

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

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

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

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

}// Of CircleIntQueue

运行结果:

第十九天:字符串匹配

19.1 String 是 Java 常用的类, 这里重新实现下部分功能.
19.2 转义符 , 有了它才能正常打印引号.
19.3 简单的越界检查.

package datastructure;

/**
 * My string. String is a class provided by the language, so I use another name.
 * It is essentially a sequential list with char type elements.
 * 
 * @author Fan Min minfanphd@163.com.
 */

public class MyString {
	/**
	 * The maximal length.
	 */
	public static final int MAX_LENGTH = 10;

	/**
	 * The actual length.
	 */
	int length;

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

	/**
	 *********************
	 * Construct an empty char array.
	 *********************
	 */
	public MyString() {
		length = 0;
		data = new char[MAX_LENGTH];
	}// Of the first constructor

	/**
	 *********************
	 * Construct using a system defined string.
	 * 
	 * @param paraString
	 *            The given string. Its length should not exceed MAX_LENGTH - 1.
	 *********************
	 */
	public MyString(String paraString) {
		data = new char[MAX_LENGTH];
		length = paraString.length();

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

	/**
	 *********************
	 * Overrides the method claimed in Object, the superclass of any class.
	 *********************
	 */
	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.println("The bound is exceeded.");
			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

	/**
	 *********************
	 * The entrance of the program.
	 * 
	 * @param args
	 *            Not used now.
	 *********************
	 */
	public static void main(String args[]) {
		MyString tempFirstString = new MyString("I like ik.");
		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 = 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

运行结果:

第二十天:综合任务

  • 面向对象与面向过程相比, 有哪些优势? 注: 第 1 - 10 天的程序, 就是面向过程的.

1.OPP更加能够应对大规模复杂程序的开发

2.OPP风格的代码更易复用、易扩展、易维护

3.OPP语言更加人性化、更加高级、更加智能

  • 比较线性表和链接的异同

1)当线性表需要频繁查找,较少插入和删除时,宜采用顺序存储结构。若需要频繁插入和删除,宜采用单链表。

2)当线性表的元素个数变化较大或不确定时,最好用单链表,这样不需要考虑存储空间大小问题。当事先知道线性表的大小长度,用顺序存储结构效率会高一些。

  • 分析线性表和链接的优缺点

 一、线性表链式存储结构的优点:

1、均匀性:虽然不同数据表的数据元素可以是各种各样的,但对于同一线性表的各数据元素必定具有相同的数据类型和长度。对于线性链表,可以从头指针开始,沿各结点的指针扫描到链表中的所有结点。

2、有序性:各数据元素在线性表中的位置只取决于它们的序号,数据元素之前的相对位置是线性的,即存在唯一的第一个和最后一个的数据元素,除了第一个和最后一个外,其它元素前面均只有一个数据元素(直接前驱)和后面均只有一个数据元素(直接后继)。

二、线性表链式存储结构的缺点:

线性表链式存储结构不要求逻辑上相邻的元素在物理位置上是相邻,因此,它没有顺序存储结构所具有的弱点,但也同时失去了顺序表可随机存取的优点。

  • 分析调拭程序常见的问题及解决方案

 常见问题有:数组越界、空指针和针对具体题目的一些问题,解决方案就是特判,做异常处理。

  • 分析链队列与循环队列的优缺点.

循环队列可以对空间重复利用,避免假溢出的现象,但是一开始就定义了队列的总长度,万一有更多的元素需要入队就不好处理,而链队列在空间上更加灵活,可以增加长度。

  • 第 18 天建立的两个队列, 其区别仅在于基础数据不同, 一个是 int, 一个是 char. 按这种思路, 对于不同的基础数据类型, 都需要重写一个类, 这样合理吗? 你想怎么样?

我认为该思路较为繁琐,可以使用模块,例如class list{},T可以是int、char以及其他的数据类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值