栈的应用(括号匹配)
任务描述: 检查一个字符串的括号是否匹配. 所谓匹配, 是指每个左括号有相应的一个右括号与之对应, 且左括号不可以出现在右括号右边. 可以修改测试字符串, 检查不同情况下的运行.
1 仅在昨天的代码基础上增加了一个 bracketMatching 方法, 以及 main 中的相应调拭语句.
2 操作系统的核心数据结构. 对于计算机而言, 如何降低时间、空间复杂度才是王道.
3 除了关注的括号, 其它字符不起任何作用.
4 一旦发现不匹配, 就直接返回, 不用罗嗦.
5 String.charAt(index):返回字符串中指定索引(index)处的字符。
package datastructure;
/**
* @time 2022/4/4
* @author Liang Huang
*/
public class CharStack {
/**The depth.
*/
public static final int MAX_DEPTH = 10;
/**
* The actual depth.
*/
int depth;
/**
* The data.
*/
char[] data;
/**
* Construct an empty 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 toSting
/**
************
*Push an element.
*
* @param paraValue The given value.
* @return Success or not.
************
*/
public boolean push(char paraValue) {
if(depth == MAX_DEPTH) {
System.out.println("Stack full.");
return false;
}//Of if
//入栈push
data[depth] = paraValue;
depth++;
return true;
}//Of push
/**
**********
*Pop an element.
*
* @return The popped char.
**********
*/
public char pop() {
if(depth == 0) {
System.out.println("Nothing to pop.");
return '\0';
}//Of if
//出栈pop
char resultChar = data[depth - 1];
depth--;
return resultChar;
}//Of pop
/**
**************
*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, 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) {
CharStack tempStack = new CharStack();
for(char ch='a'; ch<'m'; ch++) {
tempStack.push(ch);
System.out.println("The current stack is: " + tempStack.toString());
}//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);
tempExpression = ")(";
tempMatch = bracketMatching(tempExpression);
System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);
}//Of main
}//Of class CharStack
递归
1递归这个东东, 能理解的同学秒懂, 理解不了的就简直没任何办法.
2 数学式子写出来了, 直接翻译成程序, 简单方便.
3 系统会为递归建栈, 这个需要理解一下. 例如, 累加程序, 空间复杂度是 O ( n ), 因为只有运行到 paraN = 1 时, 才会弹栈.
package datastructure;
/**
* @time 2022/4/4
* @author Liang Huang
*/
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) {
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;
}else 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 = 4;
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
链队列
队列:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
特定:先进先出
1 链队列比较容易写.
2 Node 类以前是 LinkdedList 的内嵌类, 这里重写了一遍. 访问控制的事情以后再说.
3 为方便操作, 空队列也需要一个节点. 这和以前的链表同理. 头节点的引用 (指针) 称为 header.
4 入队仅操作尾部, 出队仅操作头部.
package datastructure;
/**
* @time 2022/4/4
* @author Liang Huang
*/
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);
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 == tail) {
System.out.println("No element in the queue");
return -1;
}//Of if
//出队
int resultValue = header.next.data;
header.next = header.next.next;
// The queue becomes empty.
if(header.next == null) {
header = tail;
}//Of if
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());
for(int i=0; i<5; i++) {
int tempValue = tempQueue.dequeue();
System.out.println("Looped delete " + tempValue + ", the new queue is: "
+ tempQueue.toString());
}//Of for i
for (int i = 0; i < 3; i++) {
tempQueue.enqueue(i + 10);
} // Of for i
System.out.println("Enqueue, the queue is: " + tempQueue.toString());
}//Of main
}//Of class LinkedQueue