栈 队列 背包的自己实现
在学习JavaSE以及最近做的项目之后,觉得有一种莫名的感觉,就是会感觉书写的代码不真实,没有之前使用c语言的什么东西都要自己写的麻烦感,觉得写的东西都是java帮助我完成的,什么结构方法也都有现成的,虽然很方便,但总是少了些什么,所以决定看一看数据结构这些内容,来实现自己写API,今天就看一看栈队列和背包的实现
栈
首先我们来看一看栈这种数据结构,之前接触的都是基本数据结构,而栈算是一种抽象数据结构,这种自己实现的结构在许多时候使用时会更加方便
栈是一种先进后出的数据容器(先放进去的东西会在容器的最底层存放,而新添加的数据便会在容器的最外面,可以直接取出来
我们向里面添加东西的时候会把数据放在最里面(如果栈是有大小的)
而之后添加数据 B 在添加数据C
我们现在想直接取B就是不行的 我们需要先把C拿出来才能取到B
可以看出栈是一种先进后出,后进先出的结构
那么我们先来看一看栈的API Stack 这是java.util包下的类
public class Stack imp;ements Iterable
而他的方法主要为
构造方法 Stack() 创造一个空栈
void push(Item item) 添加一个元素
Item pop() 删除最近添加的元素(并且返回这个元素)
boolean isEmpty() 栈是否为空
int size() 栈中元素的数量
void resize(int max) 改变数组大小
以及实现Iterator迭代器中的方法
boolean hasNext() 判断是否没有元素
Item next() 迭代下一个元素并返回这个元素
void remove() 删除元素
Stack中的是java中的泛型 可以理解为一个占位符 在使用时会填写上数据类型 比如String,Integer之类的数据类型
首先我们先实现这几个方法 、
public class FixedCapacityStack<Item>{
private Item[] a=(Item[]) new Object[1];//初始化创建大小为1的数组
private int N;//私有属性N来记录元素个数
public FixedCapacityStack() {//空参构造方法
super();
}
private void resize(int max) {//优化内存使用 或者扩大数组
Item[] t= (Item[])new Object[max];//使用t数组改变大小
for(int i=0;i<N;i++) {
t[i]=a[i];//再将t数组赋值
}
a=t;
}
private class ReverseArryItearator implements Iterator<Item>{
private int i=N;
public boolean hasNext() {return i>0;}
public Item next() {return a[--i];}
public void remove() {};
}
public void push(Item b) {//添加元素
if(N==a.length)resize(2*N);
a[N++]=b;
}
public int size() {
return N;//元素个数
}
public boolean isEmpty() {
return N==0;//是否为空
}
public Item pop() {
Item i=a[--N];
a[N]=null;
if(N>0&&N<a.length/4) {
resize(a.length/2);
}
return i;//返回最上层元素
}
}
但是这样虽然可以改变数组的大小但是每次改变时都要进行重新复写,这样大大的增加了代码的运行时间,降低了效率
我们有没有什么方法可以让操作的空间总是和集合的大小成正比呢,我们可以选择使用链表数据结构来存储元素
让我们看看链表版的栈
public class Stack<Item> {
private Node first;//首节点 用于存储最新添加元素
private int N;记录元素个数
private class Node{
Item item;
Node next;
}
public boolean isEmpty() {
return first==null;//或者也可以是 N==0;
}
public int size() {
return N;
}
public void push(Item it) {
Node old=first;
first=new Node();
first.item=it;
first.next=old;
N++;
}
public Item pop() {
Item it=first.item;
first=first.next;
N--;
return it;
}
}
我们可以看出链表版的栈十分有优势 每次添加或者弹出都会将内存改变而且十分少的工作量 因此我们的队列和背包也会用链表来实现
队列
队列是一种先进先出的数据结构 就像是大街上的排队一样先来先得(这个十分常见就不画图了)
我们直接来看一看代码吧
public class Queue<Item> {
private Node first;
private Node last;
private int N;
private class Node{
Item item;
Node next;
}
public boolean isEmpty() {
return first==null;//||N==0
}
public int size() {
return N;
}
public void enqueue(Item it) {
Node old=last;//队列最主要的区别就是返回的是末尾的元素
last=new Node();
last.item=it;
if(N==0) {
first=last;
}else {
old.next=last;
}
N++;
}
public Item dequeue() {
Item it=first.item;
first=first.next;
if(N==0)last=null;
N--;
return it;
}
}
这就是队列的代码
背包
最后我们来看一看背包 背包是一种更加简单的数据结构我们使用add来添加元素在使用迭代来便利元素
public class Bag<Item> implements Iterable<Item>{
private Node first;
private class Node{
Item item;
Node next;
}
public void add(Item it) {
Node old=first;
first=new Node();
first.item=it;
first.next=old;
}
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 it=current.item;
current=current.next;
return it;
}
}
}
这就是三种数据结构的自己实现