1,队列(queue)
只允许在队头(front)出,队尾(rear)进。
先进先出(FIFO,first in first out)
1)循环队列
循环队列充分利用向量空间,克服“假溢出”。
①插入删除
在循环队列中,队头指针和队尾指针的动态变化决定队列的长度。
front指定队首位置,删除一个元素就将front顺时针移动一位;
rear指向元素要插入的位置,插入一个元素就将rear顺时针移动一位;
②判断队满队空
方法一:设一布尔变量以区别队满队空。
方法二: 队满时:(rear+1)%n==front(n为队列长度)
2)操作
Throws exception Returns special value
Insert add(e) offer(e) //进队列,将元素加入队列末尾.前者返回异常,后者返回特殊值标记异常
Remove remove() poll() //获取队列头的元素并移除
Examine element() peek() //获取队列头的元素
isEmpty() //判断是否为空
2,栈(stack)
1)概念
仅在表尾进行增删的线性表。
栈顶(top)、栈底(bottom)、后进先出(LIFO,last in first out)。
将一个递归算法改为非递归算法时,通常使用栈作为辅助结构。
2)操作
栈顶指针保持不变,栈顶指针的动态变化决定栈中元素的个数。有元素入栈,栈顶指针增加,有元素出栈,栈顶指针减少。
empty()
peek()//查看栈顶内容
pop()
push(E object)
search(Object o)
3)计算
①卡特兰数
若一序列进栈顺序为e1,e2,e3,e4,e5,问存在多少种可能的出栈序列?
设n个数出栈方式有f(n)种,入栈顺序确定,记下标1、2、…、n。
设最后一个出栈的是第k个数,则说明k之前的k-1个数要完成进栈出栈,有f(k-1)种方式;
对于k之后的n-k个数再完成进栈出栈,有f(n-k)种方式;
最后第k个数出栈,这时有f(k-1)*f(n-k)种方式。
注意:每个数都有可能是最后出栈的。
所以:f(n)=f(0)*f(n-1)+f(1)*f(n-2)+…+f(k-1)*f(n-k)+…+f(n-1)*f(0);
即:f(5)=42种。
相关问题:已知前序遍历的顺序是xxxx求这棵树有多少种形状。
3,应用
1)用两个栈实现队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
解题思路:
一个栈压入元素,而另一个栈作为缓冲,将栈1的元素出栈后压入栈2中。也可以将栈1中的最后一个元素直接出栈,而不用压入栈2中再出栈。
private Stack<Integer> stack1;
private Stack<Integer> stack2;
public void push(int node) {
stack1.push(node);
}
public int pop() throws Exception {
if (stack1.isEmpty() && stack2.isEmpty()) {
throw new Exception("栈为空!");
}
if (stack2.isEmpty()) {
while(!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
2)包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
思路:定义两个栈,一个存放入的值。另一个存最小值。
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
if (stack2.isEmpty()) {
stack2.push(node);
}else {
if (stack2.peek() > node) {
stack2.push(node);
}
}
}
public void pop() {
if (stack1.pop() == stack2.peek()) {
stack2.pop();
}
}
public int top() {
return stack1.peek();
}
public int min() {
return stack2.peek();
}
3)栈的压入弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
思路:用栈来压入弹出元素,相等则出栈。
如果下一个弹出的数字是栈顶数字,弹出;
如果下一个弹出的不是栈顶数字,把压栈序列中还没有入栈的数字压入辅助栈,直到下一个需要弹出的数字压入栈顶为止。
如果所有数字都压入栈了仍未找到下一个弹出数字,那么该序列就不是一个弹出序列。
public boolean IsPopOrder(int [] pushA,int [] popA) {
if (pushA == null || popA == null) {
return false;
}
Stack<Integer> stack = new Stack<>();//辅助栈
int index = 0;
for (int i = 0; i < pushA.length; i++) {
stack.push(pushA[i]);
while (!stack.isEmpty() && stack.peek() == popA[index]) {
stack.pop();
index++;
}
}
return stack.isEmpty();
}