您的位置:首页 > 理论基础 > 数据结构算法

数据结构基础(二)栈和队列

2015-12-21 21:27 267 查看
栈和队列从数据结构的角度来看,也是线性表的一种,但比起线性表,操作少了许多。从数据类型来看,它们是和线性表大不相同的两种重要的抽象数据类型

栈(stack):后进先出(Last In First Out),简称为LIFO线性表。从线性表的特定可知,栈也有顺序栈和链栈两种

顺序栈:采用数组实现,栈的容量有限。也可用代码实现可自增容量的栈。

链栈:采用链表实现,栈的容量没有限度

下面给出顺序栈和链栈的代码。

顺序栈

/**
* 顺序栈
*/
public class Stack {
private Object[] elementDates;
private int top = 0;

public Stack() {
this.elementDates = new Object[5];
}

public int getSize() {
if (elementDates == null)
return 0;
return elementDates.length;
}

public Stack(int capacity) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.elementDates = new Object[capacity];
}

/**
* 返回栈此时的大小
* @return
*/
public int getTopPos() {
return top;
}

/**
* 弹栈
* @return
*/
public Object pop() {
if (top == 0) {
System.out.println("栈为空,无法弹出");
return null;
}
Object delEle = elementDates[--top];
return delEle;
}

/**
* 进栈
* @param o
*/
public void push(Object o) {
if (top >= elementDates.length) {
System.out.println("栈已满,不能继续加入");
return;
}
elementDates[top++] = o;
}

/**
* 返回栈顶部的元素
* @return
*/
public Object peek() {
return top==0?null:elementDates[top-1];
}
/**
* 遍历输出栈中元素
*/
public void doList() {
for (int i = 0; i < top; i++) {
System.out.print(elementDates[i] + " ");
}
System.out.println();
}

public static void main(String[] args) {
Stack stack = new Stack();
//测试空栈的弹出特例
stack.pop();
//压入几个数据进栈
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
stack.doList();
//测试弹栈出栈功能
stack.pop();
stack.doList();
stack.push(6);
stack.doList();
//测试满栈压数据的特例
stack.push(7);
System.out.println(stack.peek());
stack.doList();
}

}/*output:
栈为空,无法弹出
1 2 3 4 5
1 2 3 4
1 2 3 4 6
栈已满,不能继续加入
6
1 2 3 4 6   **/


链栈

import java.util.ArrayList;

/**
*链栈
*/
public class LinkStack {
private Node top;
private int length = 0;

/**
* 链表节点
*/
private static class Node {
Object item;
Node pre;

public Node(Object item, Node pre) {
this.item = item;
this.pre = pre;
}
}

public LinkStack() {
top = null;
}

/**
* 压栈
* @param o
*/
public void push(Object o) {
length++;
top=new Node(o, top);
}

/**
* 弹栈
* @return
*/
public Object pop() {
if (top == null) {
System.out.println("栈已为空,无法再弹出");
return null;
}
Node delNode = top;
//释放引用
delNode.pre=null;
top = top.pre;
length--;
return delNode.item;
}

/**
* 返回栈顶部的元素
* @return
*/
public Object peek() {
return top==null?null:top.item;
}
/**
* 遍历输出栈中元素
* 为了顺序输出,先存在arraylist中再反序输出
*/
public void doList() {
ArrayList<Object> list=new ArrayList<Object>();
Node t=top;
while (t!=null) {
list.add(t.item);
t=t.pre;
}

for (int i = length-1; i >=0; i--) {
System.out.print(list.get(i)+" ");
}
System.out.println("["+length+"]");
}

public static void main(String[] args) {
LinkStack linkStack = new LinkStack();
// 测试空栈的弹出特例
linkStack.pop();
// 压入几个数据进栈
linkStack.push(1);
linkStack.push(2);
linkStack.push(3);
linkStack.push(4);
linkStack.push(5);
linkStack.doList();
// 测试弹栈出栈功能
linkStack.pop();
linkStack.doList();
linkStack.push(6);
System.out.println(linkStack.peek());
linkStack.doList();
}
}/*output:
栈已为空,无法再弹出
1 2 3 4 5 [5]
1 2 3 4 [4]
6
1 2 3 4 6 [5]**/


队列

队列(queue):与栈相反,队列是一种先进先出(first in first out,简称FIFO)的线性表。它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。

顺序队列:一片连续的存储空间,设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置。每次在队尾插入一个元素是,rear增1;每次队头删除一个元素时,front增1。当rear指向分配空间之外时,尽管还有空间,出现溢出错误。

循环队列:为了解决顺序队列浪费空间,对顺序队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。

链队列:用链表实现的队列,动态创建和删除节点,效率较低,但是可以动态增长。

循环队列:

注意点:

为与rear==front队列为空的情况区分,牺牲一个空间,规定当rear在front的后面时队列已满。

为实现递增长的循环,用(i+1)%length实现

/**
*循环队列
*/
public class CircleQueue {
Object[] queue=null;
private int front=0;
private int rear=0;

/**
* 默认队列数组大小为5
*/
public CircleQueue() {
queue=new Object[5];
}

/**构造时设置队列数组长度
* @param capacity
*/
public CircleQueue(int capacity) {
if(capacity<=0){
queue=new Object[5];
return ;
}
queue=new Object[capacity];
}

/**
* 出队
* @return
*
* @author wsz
*/
public Object deQueue() {
//当rear==front时判断队列为空
if(front==rear){
System.out.println("队列为空,无法弹出");
return null;
}

Object delNode=queue[front];
front=(front+1)%queue.length;
return delNode;
}

/**
* 入队
* @param o
*
* @author wsz
*/
public void enQueue(Object o) {
//当rear在front后时判断队满
if((rear+1)%queue.length==front){
System.out.println("队列已满,无法加入"+o);
return ;
}
queue[rear]=o;
rear=(rear+1)%queue.length;
}

/**
* 遍历队列
* @author wsz
*/
public void doList() {
for (int i = front; i !=rear ; i=(i+1)%queue.length) {
System.out.print(queue[i]+" ");
}
System.out.println();
}

public static void main(String[] args) {
CircleQueue circleQueue=new CircleQueue();
circleQueue.enQueue(1);
circleQueue.enQueue(2);
circleQueue.enQueue(3);
circleQueue.enQueue(4);
circleQueue.enQueue(5);
circleQueue.doList();

circleQueue.deQueue();
circleQueue.deQueue();
circleQueue.deQueue();
circleQueue.doList();

circleQueue.enQueue(6);
circleQueue.enQueue(7);
circleQueue.doList();

circleQueue.deQueue();
circleQueue.deQueue();
circleQueue.deQueue();
circleQueue.deQueue();
circleQueue.doList();
}
}/*output:
队列已满,无法加入5
1 2 3 4
4
4 6 7
队列为空,无法弹出 **/


链队列

/**
*链队列
*/
public class LinkQueue {
/**
* 队头
*/
private Node front;

/**
* 队尾
*/
private Node rear;
/**
* 队长
*/
private int length = 0;

/**
* 链队节点
*/
private static class Node {
Object item;
Node next;

public Node(Object item, Node pre) {
this.item = item;
this.next = pre;
}
}

public LinkQueue() {
front = rear=null;
}

/**
* 入队
* @param o
*/
public void enQueue(Object o) {
length++;
Node node=new Node(o, null);
//如果此时为空队,把front和rear指向同一个节点
if(rear==null){
front=rear=node;
return ;
}
//否则直接加入,修改rear为新加入节点
rear.next=new Node(o, null);
rear=rear.next;
}

/**
* 出队
* @return
*/
public Object delQueue() {
//如果队列为空
if (front == null) {
System.out.println("队列已为空,无法出队");
return null;
}
Node delNode = front;
//修改队头为下一个节点
front = front.next;
//如果出队后没有节点,把队尾也置为空
if(front==null)
rear=front;
//释放引用
delNode.next=null;
length--;
return delNode.item;
}

/**
* 遍历输出栈中元素
* 为了顺序输出,先存在arraylist中再反序输出
*/
public void doList() {
Node node=front;
if(node==null)
return ;
while (node!=null) {
System.out.print(node.item+" ");
node=node.next;
}
System.out.println();
}

public static void main(String[] args) {
LinkQueue linkStack = new LinkQueue();
// 测试队列的弹出特例
linkStack.delQueue();
linkStack.doList();
// 压入几个数据入队
linkStack.enQueue(1);
linkStack.enQueue(2);
linkStack.enQueue(3);
linkStack.enQueue(4);
linkStack.enQueue(5);
linkStack.doList();
// 测试出队功能
linkStack.delQueue();
linkStack.delQueue();
linkStack.delQueue();
linkStack.delQueue();
linkStack.delQueue();
linkStack.doList();
linkStack.enQueue(6);
linkStack.doList();
}
}/*output:
栈已为空,无法再弹出
1 2 3 4 5
6 **/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: