8.棧的最大值問題
問題的描述和思路可以參考這裡
Java實作代碼如下:
import java.util.Stack;
/**
* 棧的最大值問題 Title: Description: Company:
*
* @author 鄭偉
* @date 2018年4月12日下午8:57:29
*/
public class SpecialStack {
Stack<Integer> stack = new Stack<>();
Stack<Integer> maxStack = new Stack<>();
public void push(Integer num) {
if (stack.isEmpty()) {
maxStack.push(num);
stack.push(num - maxStack.peek());
} else {
stack.push(num - maxStack.peek());
if (num > maxStack.peek()) {
maxStack.pop();
maxStack.push(num);
}
}
}
public int pop() {
if (!stack.isEmpty()) {
if (stack.peek() >= && !maxStack.isEmpty()) {
int result = maxStack.pop();
maxStack.push(result - stack.pop());
return result;
} else if (stack.peek() < && !maxStack.isEmpty()) {
return (maxStack.peek() + stack.pop());
} else {
return -;
}
} else {
return -;
}
}
public int max() {
if (stack.isEmpty()) {
return ;
}
if (maxStack.isEmpty())
return -;
return maxStack.peek();
}
public static void main(String[] args) {
int arr[] = { , , , , , , , , , , };
SpecialStack specialStack = new SpecialStack();
for (int i = ; i < arr.length; i++) {
specialStack.push(arr[i]);
System.out.print("入棧:" + arr[i]);
System.out.println("最大值:" + specialStack.max());
}
for (int i = ; i < arr.length; i++) {
System.out.print("出棧:" + specialStack.pop());
System.out.println("最大值:" + specialStack.max());
}
}
}
9.非遞歸實作二叉樹的周遊
前序周遊:
對于樹中的任意一個節點cur:
(1)通路cur,并将節點入棧;
(2)判斷節點cur的左孩子是否為空。若不為空,則将cur的左孩子cur.left置為目前的結點cur;
(3)若為空,則取棧頂節點并進行出棧操作(根據出棧節點去找該節點的右孩子),并将棧頂結點的右孩子cur.right置為目前的結點cur,循環至1);
中序周遊:
對于樹中的任意節點cur:
(1)若cur的左孩子不為空,将p壓棧,并将cur的左子樹置為目前節點cur,然後對目前節點重複操作。
(2)若cur的左孩子為空,将棧頂元素出棧并進行通路,把目前節點置為cur的右孩子。
(3)直到棧為空且cur為空
後序周遊:
對于樹中的任意節點cur
(1) 如果該節點沒有左孩子和右孩子可以直接通路該節點;
如果其左孩子和右孩子被通路過了,可以直接通路該節點;
(2)如果不是情況(1),那麼就先将右孩子壓棧,再将左孩子壓棧,這樣出棧順序就是先出左孩子再出右孩子。
import java.util.Stack;
/**
* 非遞歸的樹的周遊 Title: Description: Company:
*
* @author 鄭偉
* @date 2018年4月13日下午3:37:12
*/
public class Print_Tree {
// 先序周遊非遞歸
// 如果發現右兒子沒有了,那麼出棧,指向cur,如果cur右兒子有那麼久列印右兒子,把右兒子入棧,如果沒有右兒子,那麼久繼續出棧,出棧的節點設為cur
public static void preOrder(TreeNode pNode) {
Stack<TreeNode> stack = new Stack<>();
while (pNode != null || !stack.isEmpty()) {
while (pNode != null) {
// 先列印目前節點
System.out.print(pNode.val+" ");// 若節點不為空先通路再壓棧
stack.push(pNode);// 目前節點入棧
pNode = pNode.left;// 将目前節點置為p的左孩子,若不為空繼續通路并壓棧
}
// 當p為空時,說明根節點和左孩子列印周遊完畢了,接下來出棧周遊右孩子
if (!stack.isEmpty()) {// 左子樹不存在,那麼就是講棧頂彈出,作為目前 節點
pNode = stack.pop();
// 講目前節點設定為右邊的節點
pNode = pNode.right;
}
}
}
// 中序周遊非遞歸
// 就隻如果節點有左子樹就不停的入棧,直到左邊沒有左子樹,然後出棧,列印目前值,然後cur指向右節點。
public static void InOrder(TreeNode pNode) {
Stack<TreeNode> stack = new Stack<TreeNode>();
while (pNode != null || !stack.isEmpty()) {
// 不停的把左子樹入棧
while (pNode != null) {
stack.push(pNode);
pNode = pNode.left;
}
// 當左子樹沒有的時候,也就是如到底部了
if (stack != null) {
pNode = stack.pop();// 彈出一個節點
System.out.print(pNode.val+" ");
pNode = pNode.right;// 開始答應右邊的節點
}
}
}
// 後續周遊
// 先右子樹壓棧,再左子樹壓棧
public static void PostOrder(TreeNode pNode) {
if (pNode == null)
return;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode preNode = null;
TreeNode curNode;
stack.push(pNode);// 根節點先入棧
while (!stack.isEmpty()) {
curNode = stack.peek();
// 如果目前節點的左右子節點都為null,那麼就直接答應目前節點;
// 目前一個節點不為空并且是目前節點的左孩子或者右孩子,當是左孩子時說明目前節點右孩子為空,
// 當是右孩子時,說明左右孩子都通路過了,且都不為空
if (curNode.left == null
&& curNode.right == null
|| (preNode != null && (preNode == curNode.left || preNode == curNode.right))) {
System.out.print(curNode.val+" ");// 通路目前節點
preNode = curNode;
// curNode指向棧頂,由于列印過了,就直接出棧
stack.pop();
} else {
// 目前節點為棧頂元素 如果目前節點不是葉子節點,在目前節點之前通路的那個節點不是目前節點的孩子,則進行壓棧
// 先壓棧右節點再壓棧左節點 這樣出棧時是先左後右
if (curNode.right != null)
stack.push(curNode.right);
if (curNode.left != null)
stack.push(curNode.left);
}
}
}
public TreeNode buildTree(int[] nums, int i) {
if (i >= nums.length)
return null;
TreeNode root = new TreeNode(nums[i]);
root.left = buildTree(nums, i * + );
root.right = buildTree(nums, i * + );
return root;
}
public static void main(String[] args) {
Print_Tree pTree = new Print_Tree();
int[] nums = {,,,,,};
TreeNode buildTree = pTree.buildTree(nums, );
System.out.println("前序周遊");
Print_Tree.preOrder(buildTree);
System.out.println();
System.out.println("中周遊");
Print_Tree.InOrder(buildTree);
System.out.println();
System.out.println("後序周遊");
Print_Tree.PostOrder(buildTree);
}
}
/**
*前序周遊
*1 2 4 5 3 6
*中周遊
*4 2 5 1 6 3
*後序周遊
*4 5 2 6 3 1
*/