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 
时间: 2024-08-06 06:33:57

1.3 Bags, Queues, and Stacks(算法 Algorithms 第4版)(一)的相关文章

ubuntu命令行下java工程编辑与算法(第四版)环境配置

ubuntu命令行下java工程编辑与算法(第四版)环境配置 java 命令行 javac java 在学习算法(第四版)中的实例时,因需要安装配套的java编译环境,可是在编译java文件的时候总是出各种错误,特在此总结一下. ubuntu下java环境配置 由于网上教程比较多,而且也较全面,特此摆放一个链接,跟着此教程总就可以配置好oracle的java jdk,如果想更加省事,直接在命令行下键入java,会提示安装各种开源java jdk,只需要一个命令即可: sudo apt-get i

算法(第4版)PDF下载

网盘下载地址:算法(第4版)PDF下载 – 易分享电子书PDF资源网 作者: 塞奇威克 (Robert Sedgewick) / 韦恩 (Kevin Wayne) 出版社: 人民邮电出版社 原作名: Algorithms 4th edition 译者: 谢路云 出版年: 2012-10-1 页数: 636 定价: 99.00元 装帧: 平装 内容简介 · · · · · · 本书全面讲述算法和数据结构的必备知识,具有以下几大特色. ? 算法领域的经典参考书 Sedgewick畅销著作的最新版,反

排序算法总结(C语言版)

1.    插入排序 1.1     直接插入排序 1.2     Shell排序 2.    交换排序 2.1     冒泡排序 2.2     快速排序 3.    选择排序 3.1     直接选择排序 3.2     堆排序 4.    归并排序 4.1     二路归并排序 4.2     自然合并排序 5.    分布排序 5.1     基数排序 1.插入排序 1.1      直接插入排序 将已排好序的部分num[0]~num[i]后的一个元素num[i+1]插入到之前已排好序的

算法(第四版)C#题解&mdash;&mdash;1.3.49 用 6 个栈实现一个 O(1) 队列

因为这个解法有点复杂,因此单独开一贴介绍. <算法(第四版)>中的题目是这样的: 1.3.49 栈与队列.用有限个栈实现一个队列,保证每个队列操作(在最坏情况下)都只需要常数次的栈操作. 那么这里就使用六个栈来解决这个问题. 这个算法来自于这篇论文. 原文里用的是 Pure Lisp,不过语法很简单,还是很容易看懂的. 先导知识--用两个栈模拟一个队列 如何使用两个栈来模拟一个队列操作? 这是一道很经典的题目,答案也有很多种,这里只介绍之后会用到的一种方法. 首先我们有两个栈,H 和 T,分别

算法(第4版)-1.4.9 内存

总结:本小节讲述了Java的内存分配机制以及各种数据结构所使用的内存量. 重点: 1. 计算机中的电路很大一部分的作用就是帮助程序保存一些值并在稍后取出它们. 2. 计算机上的Java对内存的使用经过了精心的设计(程序的每个值在每次运行时所需的内存量都是一样的),但实现了Java的设备非常多,而内存的使用是和实现相关的. 3. 原始数据类型的常见内存.需求见算法(第4版)-1.1.2 原始数据类型与表达式. 4. · 对象本身的开销:16字节 · 对象的引用(内存地址):8字节 · 一般内存的使

“《算法》第4版第2章‘排序’”:初级排序算法(选择、冒泡、插入、希尔)

<算法>第4版作者是Robert Sedgewick 和 Kevin Wayne. 1. 选择排序 选择排序可以说是最简单的排序方法.首先,找到数组中最小的那个元素:其次,将它与数组的第一个元素交换位置(如果第一个元素就是最小元素,那么它就和自己交换):再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置.如此往复,直到将整个数组排序. 该书中提出一个命题:对于长度为N的数组,选择排序需要大约N2/2次比较和N次交换.  程序如下: 1 void SelectionSort::s

“《算法》第四版第2章‘排序’”:初级排序算法

<算法>第4版作者是Robert Sedgewick 和 Kevin Wayne. 1. 选择排序 2. 冒泡排序 3. 插入排序 4. 希尔排序

《算法》第四版 IDEA 运行环境的搭建

<算法>第四版 IDEA 运行环境的搭建 新建 模板 小书匠 在搭建之初,我是想不到会出现如此之多的问题.我看了网上的大部分教程,都是基于Eclipse搭建的,还没有使用IDEA搭建的教程.我相信许多读者跟我一样,在学习Java的时候没有使用过命令行编译的形式去运行Java代码,直接使用Eclipse工具去进行开发的,因此,当看到书中 % java BinarySerach xxx.txt < xxx.txt 的时候,不免有点不知所措.笔者现在使用的IDE是IDEA,因此是想要在IDEA

算法导论 第三版 中文版

下载地址:网盘下载 算法导论 第三版 中文版 清晰 PDF,全书共8部分35章节,内容涵盖基础知识.排序和顺序统计量.数据结构.高级设计和分析技术.高级数据结构.图算法.算法问题选编.以及数学基础知识.非常实用的参考书和工程实践手册.此外,其他资源也已经上传,全部免费,欢迎大家下载! 第3版的主要变化 1.新增了van Emde Boas树和多线程算法,并且将矩阵基础移至附录. 2.修订了递归式(现在称为"分治策略")那一章的内容,更广泛地覆盖分治法. 3.移除两章很少讲授的内容:二项