栈与队列部分
- 1.3.1为FixedCapacityStackOfString添加一个方法isFull()
- 1.3.2给定一下输入,java Stack的输出时什么
- 1.3.3 假设某个用例程序会进行一系列入栈和出栈的混合操作,入栈操作会将整数0到9按顺序压入栈;出栈操作会打印出返回值。下面哪种序列是不可能产生的?
- 1.3.4编写一个Stack的用例Parentheses,从标准输入中读取一个文本流并使用栈判定其中的括号是否配对完整.例如[()]{}{[()]}为true,对于[(])程序则打印false。
- 1.3.5 当N为50时下面这段代码会打印什么?从较高的抽象层次描述给定正整数N时这段代码的行为。
- 1.3.6下面这段代码对对陈列q进行了什么操作?
- 1.3.7 为Stack添加一个方法peek(),返回栈中最近添加的元素(而不弹出它)。
- 1.3.8给定以下输出,给出DoublingStackOfStrings的数组的内容和大小。
- 1.3.9编写一段程序,从标准输入得到一个缺少左括号的表达式并打印出补全括号之后的中序表达式。
- 1.3.10 & 1.3.11 编写一个过滤器InfixToPostfix,将算术表达式由中序表达式转为后序表达式。并编写一个程序求解后序表达式的值并打印。
- 1.3.12 编写一个可迭代的Stack用例,它含有一个静态的copy()方法,接受一个字符串的栈作为参数并返回该栈的一个副本。 注意:这种能力是迭代器价值的一个重要体现,因为有了它我们无需改变基本API就能够实现这种功能。
- 1.3.13 假设某个用例程序会进行一系列入列和出列的混合队列操作。入列操作会将整数0到9按顺序插入队列;出列操作会打印出返回值。下面哪种序列是不可能产生的?
- 1.3.14 编写一个类ResizingArrayQueueOfStrings,使用定长数组实现队列的抽象,然后扩展实现,使用调整数组的方法突破大小的限制 。
- 1.3.15 编写一个Queue用例,接受一个命令行参数k并打印出标准输入中的倒数第k个字符串(假设标准输入中至少有k个字符串)。
- 1.3.16 使用1.3.1.5节中的readInts()作为模板为Date编写一个静态方法readDates(),从标准输入中读取由练习1.2.19的表格所指定的格式的多个日期并返回一个他们的数组。
- 1.3.17 为Transaction类完成练习1.3.16。
1.3.1为FixedCapacityStackOfString添加一个方法isFull()
public class FixedCapacityStackOfStrings
{
private String[] a; // stack entries
private int N; // size
public FixedCapacityStackOfStrings(int cap)
{ a = new String[cap]; }
public boolean isEmpty() { return N == 0; }
public int size() { return N; }
public void push(String item)
{ a[N++] = item; }
public String pop()
{ return a[--N]; }
public boolean isFull(){return N==a.length;}
}
1.3.2给定一下输入,java Stack的输出时什么
it was - the - best - of -times - - - it was -the - -
输出:was best times of the was the it
1.3.3 假设某个用例程序会进行一系列入栈和出栈的混合操作,入栈操作会将整数0到9按顺序压入栈;出栈操作会打印出返回值。下面哪种序列是不可能产生的?
(a) 4 3 2 1 0 9 8 7 6 5
(b) 4 6 8 7 5 3 2 9 0 1
© 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
bfg出错
1.3.4编写一个Stack的用例Parentheses,从标准输入中读取一个文本流并使用栈判定其中的括号是否配对完整.例如[()]{}{[()]}为true,对于[(])程序则打印false。
写法为了做题而做题了,没怎么考虑其他情况。
public static void main(String[] args)
{
String std=StdIn.readString();
char[] ctd=std.toCharArray();
int flag=1;
Stack<Character> stk=new Stack<Character>();
for(int i=0;i<ctd.length;i++){
if('('==ctd[i])
stk.push(ctd[i]);
else if('['==ctd[i])
stk.push(ctd[i]);
else if('{'==ctd[i])
stk.push(ctd[i]);
else {
char p=stk.pop();//直接在判断中pop会报错
if((int)(ctd[i]-p)>2||(int)(ctd[i]-p)<0){
flag=0;
break;
}
}
}
StdOut.println(flag==0?false:true);
}
1.3.5 当N为50时下面这段代码会打印什么?从较高的抽象层次描述给定正整数N时这段代码的行为。
Stack<Integer> stack = new Stack<Integer>();
while (N > 0)
{
stack.push(N % 2);
N = N / 2;
}
for (int d : stack) StdOut.print(d);
StdOut.println();
打印的是N的二进制(当N为50时):110010
1.3.6下面这段代码对对陈列q进行了什么操作?
Stack<String> stack = new Stack<String>();
while (!q.isEmpty())
stack.push(q.dequeue());
while (!stack.isEmpty())
q.enqueue(stack.pop());
反转队列
1.3.7 为Stack添加一个方法peek(),返回栈中最近添加的元素(而不弹出它)。
public Item peek(){
if(size()==0)
throw new EmptyStackException();
return first.item;
1.3.8给定以下输出,给出DoublingStackOfStrings的数组的内容和大小。
书中并没有DoublingStackOfStrings,从下面网址上找的这个类。
https://www.cnblogs.com/furzoom/p/7710198.html
public class DoublingStackOfStrings<Item> implements Iterable<Item>
{
@SuppressWarnings("unchecked")
private Item[] a = (Item[]) new Object[1];
private int n;
public int size()
{
return n;
}
public boolean isEmpty()
{
return n == 0;
}
public void push(Item item)
{
if (n == a.length) resize(2 * n);
a[n++] = item;
}
public Item pop()
{
Item item = a[--n];
a[n] = null;
if (n > 0 && n == a.length / 4) resize(n * 2);
return item;
}
public int arraySize()
{
return a.length;
}
private void resize(int max)
{
@SuppressWarnings("unchecked")
Item[] temp = (Item[]) new Object[max];
for (int i = 0; i < n; i++)
temp[i] = a[i];
a = temp;
}
@Override
public Iterator<Item> iterator()
{
return new ArrayIterator();
}
private class ArrayIterator implements Iterator<Item>
{
private int i = n - 1;
@Override
public boolean hasNext()
{
return i >= 0;
}
@Override
public Item next()
{
return a[i--];
}
}
}
1.3.9编写一段程序,从标准输入得到一个缺少左括号的表达式并打印出补全括号之后的中序表达式。
例如: 给定输入 1+2)3-4)5-6)))
你的程序应该暑促输出 : ((1+2)((3-4)(5-6)))
public static void main(String[] args)
{
String std=StdIn.readString();
char[] ch=std.toCharArray();
Stack<String> number=new Stack<String>();
Stack<String> symbol=new Stack<String>();
for(int i=0;i<std.length();i++){
int j=i+1;
String ss= "";//把字符转为字符串压入栈中
String ss2="";//在取值时,用于接收第一次出栈
if(ch[i]>=48&&ch[i]<=57){
ss=ss+ch[i];
//while判断数字中是否有多位数
while(ch[j]>=48&&ch[j]<=57&&j<std.length()||ch[j]=='.'){
ss=ss+ch[j];
j++;
}
i=j-1;//当j变化后i也需要变化
number.push(ss);
}
else if(ch[i]==47||ch[i]==45||ch[i]==43||ch[i]==42)
symbol.push(ss+ch[i]);
else if(ch[i]==')'){
ss2=number.pop();
ss="("+number.pop()+symbol.pop()+ss2+ch[i];
number.push(ss);
}
}
StdOut.println(number.pop());
}
1.3.10 & 1.3.11 编写一个过滤器InfixToPostfix,将算术表达式由中序表达式转为后序表达式。并编写一个程序求解后序表达式的值并打印。
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
String std=StdIn.readString();
char[] ch=std.toCharArray();
StdOut.println(InfixToPostfix(ch));
double result=EvaluatePostfix(InfixToPostfix(ch).toCharArray());
StdOut.printf("%.2f\n", result);
}
public static String InfixToPostfix(char[] ch){
Stack<Character>s=new Stack<Character>();
String result="";
for (int i=0;i<ch.length;i++){
//如果是"(",压入栈中
if(ch[i]=='(')
s.push(ch[i]);
//如果是")",连续出栈,直到弹出"("为止
else if(ch[i]==')'){
while(!(s.peek()=='(')&&!s.isEmpty()){
result+=String.valueOf(s.pop());
}
s.pop();
}
//是运+-*/算符
else if(ch[i]=='+'||ch[i]=='-'||ch[i]=='*'||ch[i]=='/'){
if(s.isEmpty())
s.push(ch[i]);
//如果此运算符不大于栈顶运算符优先级,栈顶运算符出栈,此运算符进栈
else if(priority(s.peek(),ch[i])){
//while循环保证高优先级运算符全部出栈
while(!s.isEmpty()&& priority(s.peek(),ch[i])&&!s.peek().equals("("))
result+=String.valueOf(s.pop());
s.push(ch[i]);
}
//运算符连续入栈
else
s.push(ch[i]);
}
//直接保存数值
else
result+=String.valueOf(ch[i]);
}
while(!s.isEmpty())
result+=String.valueOf(s.pop());
return result;
}
public static boolean priority(char a,char b){
if((a=='*'||a=='/')&&(b=='*'||b=='/'))
return true;
else if((a=='*'||a=='/')&&(b=='+'||b=='-'))
return true;
else if((a=='+'||a=='-')&&(b=='+'||b=='-'))
return true;
else return false;
}
public static double EvaluatePostfix(char[] ch){
//使用String栈是因为当结果为负数时,可以用parseDouble转为负数
Stack<String> s=new Stack<String>();
double a,b;
for(int i=0;i<ch.length;i++){
//如果是数据,就把数据转为字符串放入栈中
if(ch[i]>=48&&ch[i]<=57){
s.push(String.valueOf(ch[i]));
}
//如果是运算符,出栈两个数据进行运算,然后再放回栈中
else {
b=Double.parseDouble(s.pop());
a=Double.parseDouble(s.pop());
switch(ch[i]){
case '+': s.push(String.valueOf(a+b));break;
case '-': s.push(String.valueOf(a-b));break;
case '*': s.push(String.valueOf(a*b));break;
case '/': s.push(String.valueOf(a/b));break;
}
}
}
return Double.parseDouble(s.pop());
}
}
1.3.12 编写一个可迭代的Stack用例,它含有一个静态的copy()方法,接受一个字符串的栈作为参数并返回该栈的一个副本。 注意:这种能力是迭代器价值的一个重要体现,因为有了它我们无需改变基本API就能够实现这种功能。
由于栈的迭代器是先进后出的迭代器,实现时需要注意方向问题。
public static <Item> Stack<Item> copy(Stack<Item> stack)
{
Iterator<Item> item = stack.iterator();
Stack<Item> result = new Stack<Item>();
Stack<Item> temp = new Stack<Item>();
while (item.hasNext()) {
temp.push(item.next());
}
item = temp.iterator();
while (item.hasNext()) {
result.push(item.next());
}
return result;
}
1.3.13 假设某个用例程序会进行一系列入列和出列的混合队列操作。入列操作会将整数0到9按顺序插入队列;出列操作会打印出返回值。下面哪种序列是不可能产生的?
(a) 0 1 2 3 4 5 6 7 8 9
(b) 4 6 8 7 5 3 2 9 0 1
© 2 5 6 7 4 8 9 3 1 0
(d) 4 3 2 1 0 5 6 7 8 9
(b)(c)(d)均是不可能产生的
1.3.14 编写一个类ResizingArrayQueueOfStrings,使用定长数组实现队列的抽象,然后扩展实现,使用调整数组的方法突破大小的限制 。
在edu.princeton.cs.algs4包中找到的ResizingArrayQueue类的实现
public class ResizingArrayQueue<Item> implements Iterable<Item> {
private Item[] q; // queue elements
private int n; // number of elements on queue
private int first; // index of first element of queue
private int last; // index of next available slot
public ResizingArrayQueue() {
q = (Item[]) new Object[2];
n = 0;
first = 0;
last = 0;
}
public boolean isEmpty() {
return n == 0;
}
public int size() {
return n;
}
// resize the underlying array
private void resize(int capacity) {
assert capacity >= n;
Item[] temp = (Item[]) new Object[capacity];
for (int i = 0; i < n; i++) {
temp[i] = q[(first + i) % q.length];
}
q = temp;
first = 0;
last = n;
}
public void enqueue(Item item) {
// double size of array if necessary and recopy to front of array
if (n == q.length) resize(2*q.length); // double size of array if necessary
q[last++] = item; // add item
if (last == q.length) last = 0; // wrap-around
n++;
}
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
Item item = q[first];
q[first] = null; // to avoid loitering
n--;
first++;
if (first == q.length) first = 0; // wrap-around
// shrink size of array if necessary
if (n > 0 && n == q.length/4) resize(q.length/2);
return item;
}
public Item peek() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
return q[first];
}
public Iterator<Item> iterator() {
return new ArrayIterator();
}
// an iterator, doesn't implement remove() since it's optional
private class ArrayIterator implements Iterator<Item> {
private int i = 0;
public boolean hasNext() { return i < n; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = q[(i + first) % q.length];
i++;
return item;
}
}
public static void main(String[] args) {
ResizingArrayQueue<String> queue = new ResizingArrayQueue<String>();
while (!StdIn.isEmpty()) {
String item = StdIn.readString();
if (!item.equals("-")) queue.enqueue(item);
else if (!queue.isEmpty()) StdOut.print(queue.dequeue() + " ");
}
StdOut.println("(" + queue.size() + " left on queue)");
}
}
1.3.15 编写一个Queue用例,接受一个命令行参数k并打印出标准输入中的倒数第k个字符串(假设标准输入中至少有k个字符串)。
public static void main(String[] args) throws Exception {
Queue<String> que=new Queue<String>();
StdOut.printf("请输入一个正整数\n");
int k=StdIn.readInt();
StdOut.printf("请输入字符串,输入#结束z\n");
while(!StdIn.isEmpty()){
String ss= StdIn.readString();
que.enqueue(ss);
}
StdOut.println(InputK(k,que));
}
public static String InputK(int k,Queue<String> queue) throws Exception{
if(k<1&&queue.isEmpty()&&k>=queue.size())
throw new Exception("k值过大或者队列为空或者k小于1");
int temp=queue.size()-k;
for(int i=0;i<temp;i++){
queue.dequeue();
}
return queue.dequeue();
}
1.3.16 使用1.3.1.5节中的readInts()作为模板为Date编写一个静态方法readDates(),从标准输入中读取由练习1.2.19的表格所指定的格式的多个日期并返回一个他们的数组。
自己创建了个test.txt文件,内容如下。
3/26/1999 6/2/1997
5/12/1989 4/15/1969
public static void main(String[] args) {
Date[] date = readDate("test.txt");
for(int i=0;i<date.length;i++)
StdOut.println(date[i].toString());
}
public static Date[] readDate(String name){
Queue<Date> queue=new Queue<Date>();
In in =new In(name);
while(!in.isEmpty()){
queue.enqueue(new Date(in.readString()));
}
Date[] date=new Date[queue.size()];
for(int i=0;i<date.length;i++){
date[i]=queue.dequeue();
}
return date;
}
1.3.17 为Transaction类完成练习1.3.16。
自己创建了个test2.txt文件,内容如下。
Turning 5/22/1939 11.99
Turning 5/22/1939 11.99
Turning 5/22/1939 11.99
Turning 5/22/1939 11.99
public static void main(String[] args) {
Transaction[] date = readdate("test2.txt");
for(int i=0;i<date.length;i++)
StdOut.println(date[i].toString());
}
public static Transaction[] readdate(String name){
Queue<Transaction> queue=new Queue<Transaction>();
In in =new In(name);
while(!in.isEmpty()){
String sdate=in.readLine();
String[] ssdate= sdate.split(" ");
Transaction transaction = new Transaction(ssdate[0], new Date(ssdate[1]), Double.parseDouble(ssdate[2]));
queue.enqueue(transaction);
}
Transaction[] tdate=new Transaction[queue.size()];
for(int i=0;i<tdate.length;i++){
tdate[i]=queue.dequeue();
}
return tdate;
}