1.3 Bags, Queues, and Stacks(算法 Algorithms 第4版)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.3 Bags, Queues, and Stacks(算法 Algorithms 第4版)相关的知识,希望对你有一定的参考价值。
1.3.1
package com.qiusongde; import java.util.Iterator; import java.util.NoSuchElementException; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class FixedCapacityStackOfStrings implements Iterable<String> { private String[] a; private int n; public FixedCapacityStackOfStrings(int cap) { a = new String[cap]; n = 0; } public void push(String item) { if(isFull()) throw new IndexOutOfBoundsException("FiexdCapcityStackOfString is Full"); a[n++] = item; } public String pop() { if(isEmpty()) throw new NoSuchElementException("FiexdCapcityStackOfString is empty"); return a[--n]; }
//1.3.1 public boolean isFull() { return n == a.length; } public boolean isEmpty() { return n == 0; } public int size() { return n; } @Override public Iterator<String> iterator() { return new ReverseArrayIterator(); } private class ReverseArrayIterator implements Iterator<String> { private int i = n; @Override public boolean hasNext() { return i > 0; } @Override public String next() { return a[--i]; } } public static void main(String[] args) { int max = 5; FixedCapacityStackOfStrings stack = new FixedCapacityStackOfStrings(max); StdOut.println("stack initialized max size is:" + max); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) { if(stack.isFull()) StdOut.println("push error, stack full"); else { stack.push(item); StdOut.println("push success:" + item + " size:" + stack.size()); StdOut.print("Left on stack: "); for (String s : stack) { StdOut.print(s + " "); } StdOut.println(); } } else { if(stack.isEmpty()) StdOut.println("pop error, stack empty"); else { StdOut.println("pop success:" + stack.pop() + " size:" + stack.size()); StdOut.print("Left on stack: "); for (String s : stack) { StdOut.print(s + " "); } StdOut.println(); } } } } }
stack initialized max size is:5 to push success:to size:1 Left on stack: to be push success:be size:2 Left on stack: be to or push success:or size:3 Left on stack: or be to not push success:not size:4 Left on stack: not or be to to push success:to size:5 Left on stack: to not or be to be push error, stack full - pop success:to size:4 Left on stack: not or be to - pop success:not size:3 Left on stack: or be to - pop success:or size:2 Left on stack: be to - pop success:be size:1 Left on stack: to - pop success:to size:0 Left on stack: - pop error, stack empty
1.3.2
was best times of the was the it (1 left on stack)
1.3.3
(a) 4 3 2 1 0 9 8 7 6 5 (b) 4 6 8 7 5 3 2 9 0 1 (c) 2 5 6 7 4 8 9 3 1 0 (d) 4 3 2 1 0 5 6 7 8 9 (e) 1 2 3 4 5 6 9 8 7 0 (f) 0 4 6 5 3 8 1 7 2 9 (g) 1 4 7 9 8 6 5 3 0 2 (h) 2 1 4 3 6 5 8 7 9 0
解题思路:
因为栈是后进先出的,又是按0到9这个顺序进行压栈的(push),因此如果pop出了某个值x,则后边比x小的值出现的顺序必须是逆序的。
举例,如果出现了4,则后边0 1 2 3出现的顺序必须是逆序的。
b中0 1不满足要求。
f中3 1 2不满足要求。
g中3 0 2不满足要求。
1.3.4
主要思路:
遇到左括号则一直压栈,遇到右括号时则从栈中弹出一个元素。
如果此时栈为空,则返回false。
如果这个元素与右括号不匹配,则返回false。
重复此过程,最后判断栈是否为空,若为空则返回true,否则返回false。
//1.3.4 //parentheses package com.qiusongde; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Parentheses { private static final char LEFT_PAREN = ‘(‘; private static final char RIGHT_PAREN = ‘)‘; private static final char LEFT_BRACE = ‘{‘; private static final char RIGHT_BRACE = ‘}‘; private static final char LEFT_BRACKET = ‘[‘; private static final char RIGHT_BRACKET = ‘]‘; public static void main(String[] args) { String input = StdIn.readAll().trim(); StdOut.println("input:" + input); StdOut.println(isParenBalanced(input)); } public static boolean isParenBalanced(String input) { Stack<Character> stack = new Stack<Character>(); for(int i = 0; i < input.length(); i++) { char pare = input.charAt(i); if(pare == LEFT_PAREN) stack.push(pare); if(pare == LEFT_BRACE) stack.push(pare); if(pare == LEFT_BRACKET) stack.push(pare); if(pare == RIGHT_PAREN) { if(stack.isEmpty()) return false; if(stack.pop() != LEFT_PAREN) return false; } if(pare == RIGHT_BRACE) { if(stack.isEmpty()) return false; if(stack.pop() != LEFT_BRACE) return false; } if(pare == RIGHT_BRACKET) { if(stack.isEmpty()) return false; if(stack.pop() != LEFT_BRACKET) return false; } } if(stack.isEmpty()) return true; else return false; } }
1.3.5
输出N的二进制表示
1.3.6
反转队列q的元素顺序
1.3.7
package com.qiusongde; import java.util.Iterator; import java.util.NoSuchElementException; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Stack<Item> implements Iterable<Item> { private Node first; private int n; private class Node { Item item; Node next; } public Stack() { first = null; n = 0; } public void push(Item item) { Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; n++; } public Item pop() { if(isEmpty()) throw new NoSuchElementException("Stack is empty"); Item item = first.item; first = first.next; n--; return item; } //1.3.7 public Item peek() { if(isEmpty()) throw new NoSuchElementException("Stack is empty"); return first.item; } public boolean isEmpty() { return first == null; } public int size() { return n; } @Override public Iterator<Item> iterator() { return new StackIterator(); } private class StackIterator implements Iterator<Item> { private Node current = first; @Override public boolean hasNext() { return current != null; } @Override public Item next() { if(!hasNext()) throw new NoSuchElementException("Stack is empty"); Item item = current.item; current = current.next; return item; } @Override public void remove() { throw new UnsupportedOperationException("Stack don‘t support remove"); } } public static void main(String[] args) { Stack<String> stack = new Stack<String>(); StdOut.println("Initialized size:" + stack.size()); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) { stack.push(item); StdOut.println("push success:" + item + " size:" + stack.size()); StdOut.print("Left on stack: "); for (String s : stack) { StdOut.print(s + " "); } StdOut.println(); } else { if(stack.isEmpty()) StdOut.println("pop error, stack empty"); else { StdOut.println("pop success:" + stack.pop() + " size:" + stack.size()); StdOut.print("Left on stack: "); for (String s : stack) { StdOut.print(s + " "); } StdOut.println(); } } } } }
1.3.8
//1.3.8 package com.qiusongde; import java.util.Iterator; import java.util.NoSuchElementException; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class ResizingArrayStack<Item> implements Iterable<Item> { private Item[] content; private int number; public ResizingArrayStack() { content = (Item[]) new Object[1]; number = 0; } private void resizeArray(int max) { if(max < number) throw new IllegalArgumentException("the size of new array must larger than the size of Stack"); Item[] temp = (Item[]) new Object[max]; for(int i = 0; i < number; i++) { temp[i] = content[i]; } content = temp; } public boolean isEmpty() { return number == 0; } public int size() { return number; } public void push(Item item) { if(number == content.length) resizeArray(2 * content.length); content[number++] = item; } public Item pop() { if(isEmpty()) throw new NoSuchElementException("Stack is empty"); Item item = content[--number]; content[number] = null;//Aoid loitering if(number == content.length/4 && number > 0) resizeArray(content.length/2); return item; } @Override public Iterator<Item> iterator() { return new ReverseArrayIterator(); } private class ReverseArrayIterator implements Iterator<Item> { private int i = number; @Override public boolean hasNext() { return i > 0; } @Override public Item next() { if(!hasNext()) throw new NoSuchElementException("Stack is empty"); return content[--i]; } @Override public void remove() { throw new UnsupportedOperationException(); } } //Just for test(main) private int arrayLength() { return content.length; } public static void main(String[] args) { ResizingArrayStack<String> stack = new ResizingArrayStack<String>(); StdOut.println("Initialized size:" + stack.size() + " Array Size:" + stack.arrayLength()); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) { stack.push(item); StdOut.println("push success:" + item + " size:" + stack.size() + " Array Size:" + stack.arrayLength()); StdOut.print("Left on stack: "); for (String s : stack) { StdOut.print(s + " "); } StdOut.println(); } else { if(stack.isEmpty()) StdOut.println("pop error, stack empty"); else { StdOut.println("pop success:" + stack.pop() + " size:" + stack.size() + " Array Size:" + stack.arrayLength()); StdOut.print("Left on stack: "); for (String s : stack) { StdOut.print(s + " "); } StdOut.println(); } } } } }
Initialized size:0 Array Size:1 it push success:it size:1 Array Size:1 Left on stack: it was push success:was size:2 Array Size:2 Left on stack: was it - pop success:was size:1 Array Size:2 Left on stack: it the push success:the size:2 Array Size:2 Left on stack: the it best push success:best size:3 Array Size:4 Left on stack: best the it - pop success:best size:2 Array Size:4 Left on stack: the it of push success:of size:3 Array Size:4 Left on stack: of the it times push success:times size:4 Array Size:4 Left on stack: times of the it - pop success:times size:3 Array Size:4 Left on stack: of the it - pop success:of size:2 Array Size:4 Left on stack: the it - pop success:the size:1 Array Size:2 Left on stack: it it push success:it size:2 Array Size:2 Left on stack: it it was push success:was size:3 Array Size:4 Left on stack: was it it - pop success:was size:2 Array Size:4 Left on stack: it it the push success:the size:3 Array Size:4 Left on stack: the it it - pop success:the size:2 Array Size:4 Left on stack: it it - pop success:it size:1 Array Size:2 Left on stack: it
1.3.9
主要思路:
用Dijkstra的双栈算法。
遇到数字则压入数字栈中(String)。
遇到运算符则压入运算符栈中(String)。
遇到右括号时,从数字栈和运算法栈中弹出相应的元素,生成相应的运算表达式(添加左括号)。
再次压入数字栈中(String)。
最后从数字栈中弹出最终的运算表达式。
//1.3.9 //only support +-*/ sqrt operator package com.qiusongde; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class AddLeftParentheses { public static void main(String[] args) { Stack<String> ops = new Stack<String>(); Stack<String> vals = new Stack<String>(); while(!StdIn.isEmpty()) { String s = StdIn.readString(); if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/") || s.equals("sqrt")) { ops.push(s); } else if(s.equals(")")) { String op = ops.pop();//operator String v = vals.pop();//value if(op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/")) { String subexpression = "( " + vals.pop() + " " + op + " " + v + " )"; vals.push(subexpression); } if(op.equals("sqrt")) { String subexpression = op + " ( " + v + " )"; vals.push(subexpression); } } else { vals.push(s); } } StdOut.println(vals.pop()); } }
1.3.10
主要思路:和1.3.9相似,只不过运算表达式的生成方式不一样
用Dijkstra的双栈算法。
遇到数字则压入数字栈中(String)。
遇到运算符则压入运算符栈中(String)。
遇到右括号时,从数字栈和运算法栈中弹出相应的元素,生成相应的运算表达式(后缀表示)。
再次压入数字栈中(String)。
最后从数字栈中弹出最终的运算表达式。
//1.3.10 //only support +-*/ operator package com.qiusongde; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class InfixToPostfix { public static void main(String[] args) { Stack<String> ops = new Stack<String>(); Stack<String> vals = new Stack<String>(); while(!StdIn.isEmpty()) { String s = StdIn.readString(); if(s.equals("(")) ; else if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) { ops.push(s); } else if(s.equals(")")) { String op = ops.pop();//operator String v = vals.pop();//value //only support +-*/ operator String subexpression = vals.pop() + " " + v + " " + op; vals.push(subexpression); } else { vals.push(s); } } StdOut.println(vals.pop()); } }
1.3.11
主要思路:
这个和Dijkstrad的双栈算法不太一样,后缀的计算只需要一个栈即可。
用一个栈来存数字栈即可。
遇到数字,压栈。
遇到运算法,从栈中弹出相应的数字,用该运算法计算得到结果。
再次压入栈中。
最终从栈中弹出最终运算结果。
//1.3.11 //only support +-*/ operator package com.qiusongde; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class EvaluatePostfix { public static void main(String[] args) { Stack<Double> vals = new Stack<Double>(); while(!StdIn.isEmpty()) { String s = StdIn.readString(); if(s.equals("+")) { double v = vals.pop();//second operand v = vals.pop() + v; vals.push(v); } else if(s.equals("-")) { double v = vals.pop();//second operand v = vals.pop() - v; vals.push(v); } else if(s.equals("*")) { double v = vals.pop();//second operand v = vals.pop() * v; vals.push(v); } else if(s.equals("/")) { double v = vals.pop();//second operand v = vals.pop() / v; vals.push(v); } else { vals.push(Double.parseDouble(s)); } } StdOut.println(vals.pop()); } }
测试1:( 2 + ( ( 3 + 4 ) * ( 5 * 6 ) ) )
用Evaluate计算的结果:
用InfixToPostfix转换结果:
用EvaluatePostfix计算的结果:
测试2:( ( ( 6 + 2 ) * 5 ) - ( 8 / 4 ) )
用Evaluate计算的结果:
用InfixToPostfix转换结果:
用EvaluatePostfix计算的结果:
1.3.12
package com.qiusongde; import java.util.Iterator; import java.util.NoSuchElementException; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Stack<Item> implements Iterable<Item> { private Node first; private int n; private class Node { Item item; Node next; } //1.3.12 public static Stack<String> copy(Stack<String> stack) { Stack<String> temp = new Stack<String>(); Stack<String> result = new Stack<String>(); for(String s : stack) { temp.push(s); } for(String s : temp) { result.push(s); } return result; } public Stack() { first = null; n = 0; } public void push(Item item) { Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; n++; } public Item pop() { if(isEmpty()) throw new NoSuchElementException("Stack is empty"); Item item = first.item; first = first.next; n--; return item; } //1.3.7 public Item peek() { if(isEmpty()) throw new NoSuchElementException("Stack is empty"); return first.item; } public boolean isEmpty() { return first == null; } public int size() { return n; } @Override public Iterator<Item> iterator() { return new StackIterator(); } private class StackIterator implements Iterator<Item> { private Node current = first; @Override public boolean hasNext() { return current != null; } @Override public Item next() { if(!hasNext()) throw new NoSuchElementException("Stack is empty"); Item item = current.item; current = current.next; return item; } @Override public void remove() { throw new UnsupportedOperationException("Stack don‘t support remove"); } } public static void main(String[] args) { Stack<String> stack = new Stack<String>(); StdOut.println("Initialized size:" + stack.size()); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) { stack.push(item); StdOut.println("push success:" + item + " size:" + stack.size()); StdOut.print("Left on stack: "); for (String s : stack) { StdOut.print(s + " "); } StdOut.println(); } else { if(stack.isEmpty()) StdOut.println("pop error, stack empty"); else { StdOut.println("pop success:" + stack.pop() + " size:" + stack.size()); StdOut.print("Left on stack: "); for (String s : stack) { StdOut.print(s + " "); } StdOut.println(); } } } //1.3.12 Stack<String> copy = Stack.copy(stack); StdOut.println("copy stack:"); for(String s : copy) { StdOut.print(s + " "); } StdOut.println(); } }
Initialized size:0 to push success:to size:1 Left on stack: to be push success:be size:2 Left on stack: be to or push success:or size:3 Left on stack: or be to not push success:not size:4 Left on stack: not or be to to push success:to size:5 Left on stack: to not or be to copy stack: to not or be to
1.3.13
(a) 0 1 2 3 4 5 6 7 8 9 (b) 4 6 8 7 5 3 2 9 0 1 (c) 2 5 6 7 4 8 9 3 1 0 (d) 4 3 2 1 0 5 6 7 8 9
答案:bcd
解释:因为Queue是先进先出的,而且加进队列是0-9按顺序添加的。
故任意位置上后边的数字都不能比该位置小。
(b)中3 2 0 1在4后边
(c)中1 0 在2后边
(d)中3 2 1 0 在4后边
1.3.14
//1.3.14 package com.qiusongde; import java.util.Iterator; import java.util.NoSuchElementException; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class ResizingArrayQueue<Item> implements Iterable<Item> { private Item[] content; private int head; private int tail; private int n; public ResizingArrayQueue() { content = (Item[])new Object[1]; n = head = tail = 0; } public int size() { return n; } public boolean isEmpty() { return n == 0; } private void resizeArray(int max) { if(max < n) throw new IllegalArgumentException("the size of new array must larger than the size of Queue"); Item[] temp = (Item[]) new Object[max]; for(int i = 0; i < n; i++) { temp[i] = content[(head + i) % content.length]; } head = 0; tail = n; content = temp; } public void enqueue(Item item) { if(n == content.length) {//full resizeArray(content.length * 2);//double array } content[tail++] = item; if(tail == content.length) { tail = 0;//wrap around } n++; } public Item dequeue() { if(isEmpty()) {//empty throw new NoSuchElementException("Queue is empty"); } Item item = content[head]; content[head] = null;//avoid loitering head++;//next if(head == content.length) { head = 0;//wrap around } n--; if(n == content.length/4 && n > 0) { resizeArray(content.length/2); } return item; } @Override public String toString() { String s; s = "Size:" + n + " ArrayLength:" + content.length + " head:" + head + " tail:" + tail +"\\n"; for(Item item : content) { s += item + " "; } s += "\\n"; return s; } @Override public Iterator<Item> iterator() { return new ResizingArrayQueueIterator(); } private class ResizingArrayQueueIterator implements Iterator<Item> { private int number = n;//initialize private int start = head;//initialize @Override public boolean hasNext() { return number > 0; } @Override public Item next() { if(!hasNext()) throw new NoSuchElementException("Queue is empty"); Item item = content[start++]; if(start == content.length) start = 0;//wrap around number--; return item; } @Override public void remove() { throw new UnsupportedOperationException(); } } public static void main(String[] args) { ResizingArrayQueue<String> queue = new ResizingArrayQueue<String>(); StdOut.println(queue); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) { queue.enqueue(item); StdOut.println("enqueue success:" + item); StdOut.println(queue); } else { if(queue.isEmpty()) StdOut.println("dequeue error, stack empty"); else { StdOut.println("dequeue success:" + queue.dequeue()); StdOut.println(queue); } } } StdOut.println("Left in the ResizingArrayQueue:"); for(String s : queue) { StdOut.print(s + " "); } StdOut.println(); } }
Size:0 ArrayLength:1 head:0 tail:0 null to enqueue success:to Size:1 ArrayLength:1 head:0 tail:0 to or enqueue success:or Size:2 ArrayLength:2 head:0 tail:0 to or not enqueue success:not Size:3 ArrayLength:4 head:0 tail:3 to or not null to enqueue success:to Size:4 ArrayLength:4 head:0 tail:0 to or not to be enqueue success:be Size:5 ArrayLength:8 head:0 tail:5 to or not to be null null null - dequeue success:to Size:4 ArrayLength:8 head:1 tail:5 null or not to be null null null - dequeue success:or Size:3 ArrayLength:8 head:2 tail:5 null null not to be null null null - dequeue success:not Size:2 ArrayLength:4 head:0 tail:2 to be null null - dequeue success:to Size:1 ArrayLength:2 head:0 tail:1 be null - dequeue success:be Size:0 ArrayLength:2 head:1 tail:1 null null to enqueue success:to Size:1 ArrayLength:2 head:1 tail:0 null to be enqueue success:be Size:2 ArrayLength:2 head:1 tail:1 be to Left in the ResizingArrayQueue: to be
1.3.15
package com.qiusongde; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Exercise1315 { public static void main(String[] args) { int k = Integer.parseInt(args[0]); Queue<String> queue = new Queue<>(); while(!StdIn.isEmpty()) { String s = StdIn.readString(); queue.enqueue(s); } int size = queue.size(); for(int i = 0; i < size - k; i++) { queue.dequeue(); } StdOut.println(queue.dequeue()); } }
1 2 3 4 5 6 7 8 9 10 6
1.3.16 1.3.17
略
1.3.18
Deletes from the list the node immediately following x.
1.3.19
package com.qiusongde.linkedlist; import java.util.Iterator; import java.util.NoSuchElementException; public class LinkedList<Item> implements Iterable<Item> { private Node first; private class Node { Item item; Node next; } public LinkedList() { first = null; } public void insertAtBeginning(Item item) { Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; } public Item removeFromBeginning() { if(isEmpty()) throw new NoSuchElementException("LinkedList is empty"); Item item = first.item; first = first.next; return item; } //1.3.19 public Item removeTheLast() { Node precurrent = new Node(); precurrent.next = first; Item item = null; //find the previous last node //precurrent.next is the same as current while(precurrent.next != null && precurrent.next.next != null) { precurrent = precurrent.next; } //has not found if(precurrent.next == null) { throw new NoSuchElementException("LinkedList is empty"); } item = precurrent.next.item; //some implementation will add one empty node as head, and head.next = first //if so, it‘s not necessary to have if condition here if(precurrent.next == first) first = precurrent.next.next; else precurrent.next = precurrent.next.next; return item; } public boolean isEmpty() { return first == null; } public String toString() { String s = ""; Node temp = first; while(temp != null) { Item item = temp.item; s += item + " "; temp = temp.next; } return s; } @Override public Iterator<Item> iterator() { return new ListIterator(); } private class ListIterator implements Iterator<Item> { private Node current = first; @Override public boolean hasNext() { return current != null; } @Override public Item next() { if(!hasNext()) throw new NoSuchElementException(); Item item = current.item; current = current.next; return item; } @Override public void remove() { throw new UnsupportedOperationException(); } } }
package com.qiusongde.linkedlist; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Exercise1319 { public static void main(String[] args) { LinkedList<String> list = new LinkedList<String>(); while(!StdIn.isEmpty()) { String s = StdIn.readString(); list.insertAtBeginning(s); StdOut.println("insertAtBeginning success: " + s); StdOut.println(list); } String s = list.removeTheLast(); StdOut.println("removeTheLast success: " + s); StdOut.println(list); } }
测试数据1:
to
be
or
not
to
be
结果:
insertAtBeginning success: to
to
insertAtBeginning success: be
be to
insertAtBeginning success: or
or be to
insertAtBeginning success: not
not or be to
insertAtBeginning success: to
to not or be to
insertAtBeginning success: be
be to not or be to
removeTheLast success: to
be to not or be
测试数据2:
to
结果:
insertAtBeginning success: to
to
removeTheLast success: to
测试数据3:
输入为空
结果:
Exception in thread "main" java.util.NoSuchElementException: LinkedList is empty at com.qiusongde.linkedlist.LinkedList.removeTheLast(LinkedList.java:45) at com.qiusongde.linkedlist.Exercise1319.main(Exercise1319.java:18)
1.3.20
在LinkedList类添加以下方法:
//1.3.20 public Item delete(int k) { if(k < 1) throw new IllegalArgumentException("k must larger than 1"); Node precurrent = new Node(); precurrent.next = first; Item item; while(precurrent.next != null && k > 1) { precurrent = precurrent.next; k--; } if(precurrent.next == null) throw new NoSuchElementException("LinkedList hasn‘t so many elements"); item = precurrent.next.item; if(precurrent.next == first) first = precurrent.next.next; else precurrent.next = precurrent.next.next; return item; }
package com.qiusongde.linkedlist; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Exercise1320 { public static void main(String[] args) { LinkedList<String> list = new LinkedList<String>(); while(!StdIn.isEmpty()) { String s = StdIn.readString(); list.insertAtBeginning(s); StdOut.println("insertAtBeginning success: " + s); StdOut.println(list); } int k = 5; String s = list.delete(k); StdOut.println("delete " + k + "th Element success: "+ s); StdOut.println(list); for(int i = 0; i < 4; i++) { k = 1; s = list.delete(k); StdOut.println("delete " + k + "th Element success: "+ s); StdOut.println(list); } k = 5; s = list.delete(k); StdOut.println("delete " + k + "th Element success: "+ s); StdOut.println(list); } }
测试数据:
to
be
or
not
to
结果:
insertAtBeginning success: to to insertAtBeginning success: be be to insertAtBeginning success: or or be to insertAtBeginning success: not not or be to insertAtBeginning success: to to not or be to delete 5th Element success: to to not or be delete 1th Element success: to not or be delete 1th Element success: not or be delete 1th Element success: or be delete 1th Element success: be Exception in thread "main" java.util.NoSuchElementException: LinkedList hasn‘t so many elements at com.qiusongde.linkedlist.LinkedList.delete(LinkedList.java:84) at com.qiusongde.linkedlist.Exercise1320.main(Exercise1320.java:32)
1.3.21
在LinkedList类添加以下方法:
//1.3.21 public boolean find(LinkedList<String> list, String key) { for(String s : list) { if(s.equals(key)) return true; } return false; }
测试用例:
package com.qiusongde.linkedlist; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Exercise1321 { public static void main(String[] args) { LinkedList<String> list = new LinkedList<String>(); while(!StdIn.isEmpty()) { String s = StdIn.readString(); list.insertAtBeginning(s); StdOut.println("insertAtBeginning success: " + s); StdOut.println(list); } String key = "qiu"; StdOut.println("find " + key + " :" + list.find(list, key)); key = "not"; StdOut.println("find " + key + " :" + list.find(list, key)); } }
输入数据:
to
be
or
not
to
输出结果:
insertAtBeginning success: to to insertAtBeginning success: be be to insertAtBeginning success: or or be to insertAtBeginning success: not not or be to insertAtBeginning success: to to not or be to find qiu :false find not :true
1.3.22
Insert node t immediately after node x
1.3.23
When it comes time to update t.next, x.next is no longer the original node following x, but is instead of itself!
1.3.24 1.3.25
实现过程中,Node未内部类,用private修饰,不能再外边访问。
所以这两个函数没有意义。
1.3.26
测试用例:
package com.qiusongde.linkedlist; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Exercise1326 { public static void main(String[] args) { String key = "qiu"; LinkedList<String> list = new LinkedList<String>(); while(!StdIn.isEmpty()) { String s = StdIn.readString(); list.insertAtBeginning(s); StdOut.println("insertAtBeginning success: " + s); StdOut.println(list); } list.remove(list, key); StdOut.println("remove success:" + key); StdOut.println(list); } }
方法实现:
//1.3.26 /* * remove all of the nodes in the list that have key as its item field * * @param list the linked list * @param key the key * * @return void * */ public void remove(LinkedList<String> list, String key) { Node precurrent; precurrent = findPreNode(key); //remove all of the nodes while(precurrent.next != null) { if(precurrent.next == first) first = first.next; else precurrent.next = precurrent.next.next; precurrent = findPreNode(key); } } //1.3.26 /* * find the node in the list whose item equals key * * @param key the key * * @return return the previous node whose item equals key */ private Node findPreNode(String key) { Node precurrent = new Node(); precurrent.next = first; while(precurrent.next != null && !precurrent.next.item.equals(key)) { precurrent = precurrent.next; } return precurrent; }
输入数据:
to
be
or
not
to
输出结果1:
insertAtBeginning success: to
to
insertAtBeginning success: be
be to
insertAtBeginning success: or
or be to
insertAtBeginning success: not
not or be to
insertAtBeginning success: to
to not or be to
remove success:to
not or be
输出结果2:
insertAtBeginning success: to
to
insertAtBeginning success: be
be to
insertAtBeginning success: or
or be to
insertAtBeginning success: not
not or be to
insertAtBeginning success: to
to not or be to
remove success:not
to or be to
输出结果3:
insertAtBeginning success: to
to
insertAtBeginning success: be
be to
insertAtBeginning success: or
or be to
insertAtBeginning success: not
not or be to
insertAtBeginning success: to
to not or be to
remove success:qiu
to not or be to
1.3.27 1.3.28
方法实现:
//1.3.27 /* * return the value of the maximum key in the list * * @param list the linked list of Integer * * @return return the maximum key in the list */ public static int max(LinkedList<Integer> list) { if(list.first == null) return 0; int max = 0; for(int val : list) { if(val > max) max = val; } return max; } //1.3.28 /* * return the value of the maximum key in the list by recursion * * @param list the linked list of Integer * * @return return the maximum key in the list */ public static int maxByRecursion(LinkedList<Integer> list) { if(list.first == null) return 0; int first = list.first.item;//first item list.first = list.first.next;//remove first item in the list int max = maxByRecursion(list);//calculate the maximum value of the new list if(first > max) return first; else return max; }
测试用例:
package com.qiusongde.linkedlist; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class Exercise1327 { public static void main(String[] args) { LinkedList<Integer> list = new LinkedList<Integer>(); while(!StdIn.isEmpty()) { int val = StdIn.readInt(); list.insertAtBeginning(val); StdOut.println("insertAtBeginning success: " + val); StdOut.println(list); } int max = LinkedList.max(list); StdOut.println("The maximum key is:" + max); max = LinkedList.maxByRecursion(list); StdOut.println("The maximum key is:" + max + "(By Recursion)"); } }
测试数据1:
insertAtBeginning success: 90 90 insertAtBeginning success: 78 78 90 insertAtBeginning success: 32 32 78 90 insertAtBeginning success: 6 6 32 78 90 insertAtBeginning success: 69 69 6 32 78 90 insertAtBeginning success: 26 26 69 6 32 78 90 insertAtBeginning success: 51 51 26 69 6 32 78 90 insertAtBeginning success: 100 100 51 26 69 6 32 78 90 insertAtBeginning success: 30 30 100 51 26 69 6 32 78 90 insertAtBeginning success: 25 25 30 100 51 26 69 6 32 78 90 insertAtBeginning success: 10 10 25 30 100 51 26 69 6 32 78 90 The maximum key is:100 The maximum key is:100(By Recursion)
测试数据2:
insertAtBeginning success: 90 90 insertAtBeginning success: 78 78 90 The maximum key is:90 The maximum key is:90(By Recursion)
测试数据3:
insertAtBeginning success: 90 90 The maximum key is:90 The maximum key is:90(By Recursion)
测试数据4:(输入为空)
The maximum key is:0
The maximum key is:0(By Recursion)
1.3.29
代码实现:
//1.3.29 package com.qiusongde.linkedlist; import java.util.Iterator; import java.util.NoSuchElementException; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; public class CircularQueue<Item> implements Iterable<Item> { private Node last; private int n; private class Node { Item item; Node next; } public CircularQueue() { last = null; n = 0; } public boolean isEmpty() { return last == null; } public int size() { return n; } public void enqueue(Item item) { Node oldlast = last;//save oldlast last = new Node();//new node last.item = item; if(oldlast == null) {//empty last.next = last; } else { last.next = oldlast.next;//next is first oldlast.next = last; } n++; } public Item dequeue() { if(isEmpty()) throw new NoSuchElementException("Queue is empty"); Item item = last.next.item; if(last.next == last) {//only one node last = null; } else { last.next = last.next.next; } n--; return item; } @Override public Iterator<Item> iterator() { return new CircularQueueIterator(); } private class CircularQueueIterator implements Iterator<Item> { //it is important that this class cannot change the CircularQueue //so we can only change precurrent and can‘t change precurrent.next private Node precurrent; public CircularQueueIterator() { precurrent = last; } @Override public boolean hasNext() { return precurrent != null; } @Override public Item next() { if(!hasNext()) throw new NoSuchElementException("Queue is empty"); Item item = precurrent.next.item; if(last == last.next) {//one node precurrent = null;//end } else { precurrent = precurrent.next; if(precurrent == last) {//precurrent equals last again precurrent = null;//end } } return item; } @Override public void remove() { throw new UnsupportedOperationException(); } } public static void main(String[] args) { CircularQueue<String> queue = new CircularQueue<String>(); StdOut.println("Initialized size:" + queue.size()); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) { queue.enqueue(item); StdOut.println("enqueue success:" + item + " size:" + queue.size()); StdOut.print("Left on queue: "); for (String s : queue) { StdOut.print(s + " "); } StdOut.println(); } else { if(queue.isEmpty()) StdOut.println("dequeue error, queue empty"); else { StdOut.println("dequeue success:" + queue.dequeue() + " size:" + queue.size()); StdOut.print("Left on queue: "); for (String s : queue) { StdOut.print(s + " "); } StdOut.println(); } } } } }
测试数据:
to be or not to - be - - that - - - is
输出结果:
Initialized size:0 enqueue success:to size:1 Left on queue: to enqueue success:be size:2 Left on queue: to be enqueue success:or size:3 Left on queue: to be or enqueue success:not size:4 Left on queue: to be or not enqueue success:to size:5 Left on queue: to be or not to dequeue success:to size:4 Left on queue: be or not to enqueue success:be size:5 Left on queue: be or not to be dequeue success:be size:4 Left on queue: or not to be dequeue success:or size:3 Left on queue: not to be enqueue success:that size:4 Left on queue: not to be that dequeue success:not size:3 Left on queue: to be that dequeue success:to size:2 Left on queue: be that dequeue success:be size:1 Left on queue: that enqueue success:is size:2 Left on queue: that is
以上是关于1.3 Bags, Queues, and Stacks(算法 Algorithms 第4版)的主要内容,如果未能解决你的问题,请参考以下文章
A. Dawid and Bags of Candies ( Codeforces Round #588 (Div. 2) )
Codechef APRIL14 ANUCBC Cards, bags and coins 题解
Dispatch Queues and Thread Safety
Tasks, microtasks, queues and schedules