第十一天:顺序表(一)
此处为闵老师发布学习内容理论知识,今日对理论概念进行了一定了解,在《数据结构》中, 使用“抽象数据类型”来描述不同的数据结构. 在《面向对象程序设计》中, 用对象来存储数据及其上的操作. 我认为, 它们的本质都是相同的.
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以及其他的数据类型。