1.2:背包,队列和栈

1:概念

首先介绍下三者的概念:

  1.     :所谓的“栈”也称之为“后进先出队列”,可以想像成放在桌上的一叠书,每次无论增加还是减少都在顶部。
  2. 队列:“先进先出队列”,类比生活中的排队。增加在队尾,减少在队头
  3. 背包:背包本质上和前两者没有什么不同,可以是栈,也可以是队列,使用这个概念意在表示在个别情况下元素处理的顺序不重要,可以是“先进先出”也可以是“后进先出”

这三种数据类型称之为 “集合数据类型

2:API

3:栈的数组的实现以及对其一些改进

首先为了简单起见,我们先使用数组来表示栈:

import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;

class FixedCapacityStackOfStrings {
	private String[] a;
	private int size;
	
	public FixedCapacityStackOfStrings(int n) {
		a = new String[n];
	}
	
	public void push(String item) {
		a[size++] = item;
	}
	
	public String pop() {
		return a[--size];
	}
	
	public boolean isEmpty() {
		return size == 0;
	}
	
	public int size() {
		return size;
	}
}

public class Test {
	public static void main(String args[]) {
		FixedCapacityStackOfStrings s = new FixedCapacityStackOfStrings(100);
		
		while(!StdIn.isEmpty()) {
			String item = StdIn.readString();
			if(!item.equals("-"))
				s.push(item);
			else if(!s.isEmpty()) 
				System.out.print(s.pop() + " ");
		}
		
	}
}

结果如下:


由于该种栈只支持“String”类型,所以可以用泛型对其进行改进,以便符合其它类型的栈

import edu.princeton.cs.algs4.StdIn;

class FixedCapacityStack<Item> {
	private Item[] a;
	private int size;
	
	public FixedCapacityStack(int n) {
		a = (Item[]) new Object[n];
	}
	
	public void push(Item item) {
		a[size++] = item;
	}
	
	public Item pop() {
		return a[--size];
	}
	
	public boolean isEmpty() {
		return size == 0;
	}
	
	public int size() {
		return size;
	}
}

public class Test {
	public static void main(String args[]) {
		FixedCapacityStack<String> s = new FixedCapacityStack(100);
		
		while(!StdIn.isEmpty()) {
			String item = StdIn.readString();
			if(!item.equals("-"))
				s.push(item);
			else if(!s.isEmpty()) 
				System.out.print(s.pop() + " ");
		}
		System.out.println(s.size());
	}
}

但是这样依旧还有一些缺点,比如说大小的调整。因为无法实现确定栈的大小,只能采取多分配大一些的空间,这样无疑绘很浪费。所以进一步改进如下:

import java.util.Iterator;

import edu.princeton.cs.algs4.StdIn;

class FixedCapacityStack<Item> implements Iterable<Item>{
	private Item[] a;
	private int size = 0;	//元素的大小
	
	private void resize(int len) {	//该方法将a[]大小扩大(缩小)到len
		Item[] temp = (Item[]) new Object[len];
		for(int i = 0; i < len; i++)
			temp[i] = a[i];
		a = temp;
	}
	
	public FixedCapacityStack(int n) {
		a = (Item[]) new Object[n];
	}
	
	public void push(Item item) {
		if(size == a.length)	
			resize(2 * a.length);
		
		a[size++] = item;
	}
	
	public Item pop() {
		Item item = a[--size];
		
		a[size] = null;	//避免对象游离
		if(size > 0 && size == a.length)
			resize(a.length / 2);
		
		return item;
	}
	
	public boolean isEmpty() {
		return size == 0;
	}
	
	public int size() {
		return size;
	}
	
	//为了能够使用foreach打印,实现了一个iterator()方法以及一个ReverseArrayIterator内部类
	public Iterator<Item> iterator() {
		return new ReverseArrayIterator();
	}
	
	private class ReverseArrayIterator implements Iterator<Item>{
		private int i = size;
		
		public boolean hasNext() {
			return i > 0;
		}
		
		public Item next() {
			return a[--i];
		}
		
		public void remove() {}
		
	}
}

这段代码相比前面两个做了3点优化:

  1. 实现了数组可自动调整
  2. 在pop()方法中使用了a[size] = null; 避免对象游离
  3. 新增加一个iterator()方法以及一个ReverseArrayIterator内部类,以便能够使用foreach()方法打印该对象

尽管这是数组来表示栈最好的方式,但是数组里面空间的浪费依然不可避免。所以下面给出另一种数据结构来表示栈

4:使用链表来表示栈

import java.util.Iterator;

public class Stack<Item> implements Iterable<Item>{
	private Node top;	//栈顶元素
	private int size;	//元素数量
	private class Node {
		Item item;
		Node next;
	}
	
	public boolean isEmpty() {
		return top == null;
	}
	
	public int size() {
		return size;
	}
	
	public void push(Item item) {
		Node oldTop = top;
		top = new Node();
		top.item = item;
		top.next = oldTop;
		size++;
	}
	
	public Item pop() {
		Item item = top.item;
		top = top.next;
		size--;
		
		return item;
	}
	
	//以下部分是为了实现foreach打印
	public Iterator<Item> iterator() {
		return new ListIterator();
	}
	
	private class ListIterator implements Iterator<Item> {
		private Node current = top;
		
		public boolean hasNext() {
			return current != null;
		}
		
		public void remove() {}
		
		public Item next() {
			Item item = current.item;
			current = current.next;
			return item;
		}
	}
}
public class Test {
	public static void main(String args[]) {
		Stack<String> s = new Stack();
		
		while(!StdIn.isEmpty()) {
			String item = StdIn.readString();
			if(!item.equals("-"))
				s.push(item);
			else if(!s.isEmpty()) 
				System.out.print(s.pop() + " ");
		}
		
	}
}

5:用链表实现队列以及背包

链表实现队列

import java.util.Iterator;


public class Queue<Item> implements Iterable<Item>{
	private Node first;
	private Node last;
	private int size;
	private class Node {
		Item item;
		Node next;
	}
	
	public boolean isEmpty() {
		return first == null;
	}
	
	public int size() {
		return size;
	}
	
	public void push(Item item) {
		Node oldLast = last;
		last = new Node();
		last.item = item;
		last.next = null;
		
		if(isEmpty())
			first = last;
		else
			oldLast.next = last;
		size++;
	}
	
	public Item pop() {
		Item item = first.item;
		first = first.next;
		
		if(isEmpty())
			last = null;
		size--;
		
		return item;
	}
	
	//以下部分是为了实现foreach打印
	public Iterator<Item> iterator() {
		return new ListIterator();
	}
		
	private class ListIterator implements Iterator<Item> {
		private Node current = first;
			
		public boolean hasNext() {
			return current != null;
		}
			
		public void remove() {}
			
		public Item next() {
			Item item = current.item;
			current = current.next;
			return item;
		}
	}
}


用链表实现背包

import java.util.Iterator;

public class Bag<Item> implements Iterable {
	private Node first;
	private int size;
	private class Node {
		Item item;
		Node next;
	}
	
	public void add(Item item) {
		Node oldFirst = first;
		first = new Node();
		first.item = item;
		first.next = oldFirst;
		size++;
	}
	
	//以下部分是为了实现foreach打印
	public Iterator<Item> iterator() {
		return new ListIterator();
	}
			
	private class ListIterator implements Iterator<Item> {
		private Node current = first;
				
		public boolean hasNext() {
			return current != null;
		}
				
		public void remove() {}
				
		public Item next() {
			Item item = current.item;
			current = current.next;
			return item;
		}
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值