数据结构基础(二)栈和队列
2015-12-21 21:27
267 查看
栈和队列从数据结构的角度来看,也是线性表的一种,但比起线性表,操作少了许多。从数据类型来看,它们是和线性表大不相同的两种重要的抽象数据类型
顺序栈:采用数组实现,栈的容量有限。也可用代码实现可自增容量的栈。
链栈:采用链表实现,栈的容量没有限度
下面给出顺序栈和链栈的代码。
顺序队列:一片连续的存储空间,设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置。每次在队尾插入一个元素是,rear增1;每次队头删除一个元素时,front增1。当rear指向分配空间之外时,尽管还有空间,出现溢出错误。
循环队列:为了解决顺序队列浪费空间,对顺序队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。
链队列:用链表实现的队列,动态创建和删除节点,效率较低,但是可以动态增长。
为实现递增长的循环,用(i+1)%length实现
栈
栈(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 **/
相关文章推荐
- 09 DirectoryStructure
- 数据结构实验之排序六:希尔排序
- UI day 14 XML JSON数据结构解析
- 数据结构2 二叉树的高度和宽度
- 对数据库索引的数据结构学习
- 探索 ConcurrentHashMap 高并发性的实现机制
- 数据结构:二叉搜索树(BST)的基本操作
- 数据结构:二叉搜索树(BST)的基本操作
- 数据结构与算法书籍推荐
- 2014级数据结构课程总结全链接
- Redis数据结构详解
- [Coursera]数据结构基础_Week2_线性表_Q3
- [Coursera]数据结构基础_Week2_线性表_Q2
- 数据结构基础(C语言版)(朱仲涛翻译)代码学习 第一章001
- 数据结构之排序算法(二)-冒泡排序及改进
- [Coursera]数据结构基础_Week2_线性表_Q1
- <LeetCode OJ> 50. Pow(x, n)
- 数据结构之排序算法(一)-堆排序
- 数据结构学习笔记目录
- 1003-- 蛇形矩阵 一字型和回字型