算法笔记1 背包、队列和栈


API中均包含以下四项:
1.无参构造函数
2.添加单个元素
3.是否为空
4.返回集合大小

1 泛型

Stack<String> stack = new Stack<String>();

String处是一个类型占位符,可填其余类型

2 迭代

//foreach语句,打印整个集合
Quene<Transaction> collection = new Quene<Transaction>();
for(Transaction t:collection)
{
	StdOut.println(t);
}
//与如下的while语句等价
Iterator<Transaction> i = collection.iterator();
while(i.hasNext())
{
	Transaction s = i.next();
	StdOut.println(s);
}
  • 任意可迭代的集合数据类型中需要实现的东西:
    1.实现一个Iterator()方法并返回一个Iterator对象;
    2.Iterator类必须包含两个方法:hasNext()和next()(返回集合中的一个泛型元素)

  • 用接口机制来指定一个类必须实现的方法:

public interface Iterable<Item>
{
	Iterator<Item>	iterator();//这是一个Iterator()方法,返回一个迭代器Iterator<Item>
}
//迭代器是一个实现了hasNext()和next()方法的类的对象(c++中迭代器就是指针),由以下接口所定义(即java.util.Iterator)
public interface Iterator<Item>
{
	boolean	hasNext();
	Item	next();
	void	remove();
}
//一个例子:逆序迭代遍历数组
import	java.util.Iterator;
private class ReverseArrayIterator implements Iterator<Item>
{
	private	int i = N;
	public	boolean	hasNext(){return i>0;}
	public	Item	next(){return	a[--i];}
	public	void	remove(){	}//remove()方法总为空,因为我们希望避免在迭代中穿插能够修改数据结构的操作。
}

3 Bag

不讲究顺序,目的是收集元素并迭代遍历所有收集到的元素。

public class Bag<Item> implements Iterable<Item>
	Bag()
	void	add(Item item)
	boolean	isEmpty()
	int	size()

背包的典型用例:计算输入中的所有double值的平均值和样本标准差

Bag<Double> numbers = new Bag<Double>();
while(!StdIn.isEmpty())
	numbers.add(StdIn.readDouble());

int N = numbers.size();
double sum = 0.0;
for(double x : numbers)
	sum += x;
double mean = sum/N;
sum = 0.0;
for(double x : numbers)
	sum += (x-mean)*(x-mean)
double std = Math.sqrt(sum/(N-1));

StdOut.printf(“Mean:%.2f\n”,mean);
StdOut.printf(“Std dev:%.2f\n”,std);

4 Quene

先进先出

public class Quene<Item> implements Iterable<Item>
	Quene()
	void	enquene(Item item)
	Item	dequene()	//删除最早添加的一个元素
	boolean	isEmpty()
	int	size()

队列的典型用例:无需预先知道文件的大小即可将文件中的所有整数读入一个数组

In in = new In(name);
Quene<Integer>	q = new	Quene<Integer>();
while(!in.isEmpty())
	q.enquene(in.readInt());
int N = q.size();
int[] a = new int[N];
for(int i = 0;i<N;i++)
	a[i] = q.dequeue()
return a;

5 Stack

后进先出

public class Stack<Item> implements Iterable<Item>
	Stack()
	void	push(Item item)
	Item	pop()	//删除最近添加的一个元素
	boolean	isEmpty()
	int	size()

栈的典型用例1:将输入中的所有整数逆序排列

Stack<Interger>	stack = new Stack<Interger>();
while(!StdIn.isEmpty())
	stack.push(StdIn.readInt());
for(int i : stack)
	StdOut.println(i);

栈的典型用例2:Dijkstra的双栈算术表达式求值算法
1.将操作数压入操作数栈
2.将运算符压入运算符栈
3.忽略左括号
4.在遇到右括号时,弹出一个运算符,弹出所需数量的操作数,并将运算符和操作数的运算结果压入操作数栈

Stack<String> ops = new Stack<String>();
Stack<Double> vals = new Stack<Double>();
while(!StdIn.isEmpty())
{
	String s = StdIn.readString();
	if(s.equals(());
	else if(s.equals(+))	ops.push(s);
	else if(s.equals(-))	ops.push(s);
	else if(s.equals(*))	ops.push(s);
	else if(s.equals(/))	ops.push(s);
	else if(s.equals(“sqrt”))	ops.push(s);
	else if(s.equals()))
	{
		String op = ops.pop();
		double v = vals.pop();
		if(op.equals(+))	v = vals.pop()+v;
		else if(op.equals(-))	v = vals.pop()-v;
		else if(op.equals(*)) v = vals.pop()*v;
		else if(op.equals(/))	v = vals.pop()/v;
		else if(op.equals(“sqrt”))	v = Math.sqrt(v);
		vals.push(v);
	}
	else vals.push(Double.parseDouble(s));
}
StdOut.println(vals.pop());

5.1 定容栈

容量固定的字符串栈的抽象数据类型,只能处理String值,要求用例指定一个容量且不支持迭代。FixedCapacityOfStrings(int cap)

数据类型的实现

public class FixedCapacityStackOfStrings
{
	private String[] a;
	private int N;
	public FixedCapacityOfStrings(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];	}	//栈的顶部位于a[N-1]
}

测试用例:
输入:to be or not to - be - - that - - - is
输出:to be not that or be ( 2 left on stack )

FixedCapacityStackOfStrings s;
s = new FixedCapacityStackOfStrings(100);
while(!StdIn.isEmpty())
{
	String item = StdIn.readString();
	if(!item.equals(-))
		s.push(item);
	else if(!s.isEmpty())
		StdOut.print(s.pop()+” “);
}
StdOut.println((+s.size()+”left on stack));

5.2 实现一个泛型的定容栈

对比前文给出的实现代码

public class FixedCapacityStack<Item>
{	private Item[] a;
	private int N;
	public FixedCapacityOfStrings(int cap)
	{	a = new Item[cap];	}//java不允许创建泛型数组,故这是错的
	{	a = (Item[]) new Object[cap];	}//使用了类型转换
	public boolean isEmpty()
	{	return N==0;	}
	public int size()
	{	return N;	}
	public void push(Item item)
	{	a[N++] = item;	}
	public Item pop()
	{	return a[--N];	}	//栈的顶部位于a[N-1]
}

测试用例同上:
输入:to be or not to - be - - that - - - is
输出:to be not that or be ( 2 left on stack )

FixedCapacityStack<String> s;
s = new FixedCapacityStack<String>(100);
while(!StdIn.isEmpty())
{
	String item = StdIn.readString();
	if(!item.equals(-))
		s.push(item);
	else if(!s.isEmpty())
		StdOut.print(s.pop()+” “);
}
StdOut.println((+s.size()+”left on stack));

5.3 调整数组的大小

选择用数组表示栈内容必须预先估计栈的最大容量。
正常来说,push()方法需要在代码中检测栈是否已满,也应该含有一个isFull()方法检测栈是否已满。要从处理栈是否已满的问题中解脱出来用以下方法

//将栈移动到另一个大小不同的数组中
private void resize(int max)
{
	Itemp[]	temp = (Item[])new	Object[max];
	for(int i = 0;i<N;i++)
		temp[i] = a[i]
	a = temp;
}
//在push()中检查数组是否太小
public void push(Item item)
{
	if(N == a.length)resize(2*a.length);
	a[N++] = item;
}
//在pop()中删除栈定元素
public Item pop()
{
	Item item = a[--N];
	a[N] = null;//避免**对象游离**
	if(N>0 && N == a.length/4)resize(a.length/2);
	return item;
}

算法1.1 下压栈(能够动态调整数组大小的实现)

import	java.util.Iterator;
public class ResizingArrayStack<Item>	implements	Iterable<Item>
{
	private	Item[] a = (Item())new	Object[1];//栈元素
	private	int N = 0;//元素数量
	public boolean isEmpty(){return N == 0;}
	public int	size(){return N;}
	private	void	resize(int max)
	{
		//将栈移动到一个大小为max的数组
		Item[]	temp = (Item[])new Object[max];
		for(int i = 0;i<N;i++)
			temp[i] = a[i];
		a = temp;
	}
	public void push(Item item)
	{
		if(N == a.length)resize(2*a.length);
		a[N++] = item;
	}
	public Item pop()
	{
		Item	item = a[--N];
		a[N] = null;
		if(N>0 && N = a.length/4)resize(a.length/2);
		return item;
	}
	public Iterator<Item> iterator()
	{	return	new	ReverseArrayIterator();	}
	private class ReverseArrayIterator implements Iterator<Item>
	{
		private int i = N;
		public boolean hasNext{return i>0;}
		public Item	next(){return a[--i];}
		public void remove(){	}
	}
}

这份泛型可迭代的Stack API的实现是所有集合类抽象数据类型实现的模版。它将所有元素保存在数组中,并动态调整数组的大小和栈大小之比小于一个常数。
缺点在于某些push和pop操作会调整数组的大小,这项操作的耗时和栈大小成正比。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值