数据结构与算法(4)-栈,队列,优先级队列
2018-03-20 17:47
375 查看
1.栈
先进后出,头进头出.
一般基于数组实现.
出栈操作一般不删除数据,只是指针的移动.
入栈,入栈的时间复杂度都为O(1).
栈结构主要应用:
校验表达式语法是否正确,jvm中方法的执行调用等.
代码:用数组模拟栈结构
输出:
代码:校验文本中的左右括号是否匹配
输出:
2.队列
后进后出.
数组和链表常用来实现队列.
插入和取出时间复杂度为O(1).
以数组模拟队列为例,插入时,先移动再赋值,尾部向右移动,当尾部位置为maxSize-1时,需要将尾部位置赋值-1,而下一次则在0的位置插入.
删除时,头部向右移动,先取值再移动,如果移动后的值为maxSize,需要将头部赋值为0,下一次取0的位置的值.
同时需要记录当前元素的数目.(其实队列可以理解为一个环形结构)
代码:用数组模拟队列结构
输出:
双端队列简介
一种多用途的数据机构,左右两边都可以进行插入和取出操作,需要定义以下四种方法.
insertLeft()
insertRight()
removeLeft()
removeRight()
双端队列可以通过禁用部分功能,同时做栈和队列使用.
禁用insertLeft(),removeLeft()可以作栈使用.
禁用insertLeft(),removeRight()可以作一般队列使用.
3.优先级队列
插入队列的数据有优先级的高低,优先级高的将被先取出.通常使用堆来实现优先级队列,此处暂时用数组模拟.如果将数据的值作为优先级,值越大则越先被取出.
通常将值最小的固定数组角标的0的位置,后续插入的数将进行排序和移动,取出始终取值最大的.
优先级队列的时间复杂度:插入O(N),删除O(1).
代码:数组模拟优先级队列
输出:
先进后出,头进头出.
一般基于数组实现.
出栈操作一般不删除数据,只是指针的移动.
入栈,入栈的时间复杂度都为O(1).
栈结构主要应用:
校验表达式语法是否正确,jvm中方法的执行调用等.
代码:用数组模拟栈结构
public class StackDemo { private int maxSize; //最大尺寸 private long[] longArray; //数组 private int top; //指针 public StackDemo(int maxSize){ this.maxSize = maxSize; this.longArray = new long[maxSize]; this.top = -1; } //入栈操作 public void push(long data){ if(top > this.maxSize-1){ //栈已满 System.out.println("栈已满,无法进行入栈操作!!!"); }else{ longArray[++top] = data; System.out.println(data+"被压入栈顶!!!"); } } //出栈操作 public long pop(){ if(this.isEmpty()){ try { throw new Exception(); } catch (Exception e) { e.printStackTrace(); } } //出栈只是移动指针的位置,并非删除 return longArray[top--]; } //读取栈顶 public long peek(){ return longArray[top]; } //是否为空 public boolean isEmpty(){ return -1==top; } //是否满栈 public boolean isFull(){ return (maxSize-1)==top; } public static void main(String[] args) { StackDemo stack = new StackDemo(10); stack.push(10); stack.push(10); stack.push(20); stack.push(30); while(!stack.isEmpty()){ System.out.println(stack.pop()); } } }
输出:
1 4000 0被压入栈顶!!! 10被压入栈顶!!! 20被压入栈顶!!! 30被压入栈顶!!! 30 20 10 10
代码:校验文本中的左右括号是否匹配
public class CheckCharStack { private int maxSize; private char[] charArray; private int top; public CheckCharStack(int maxSize) { this.maxSize = maxSize; this.charArray = new char[maxSize]; this.top = -1; } // 判断满栈 public boolean isFull() { return (maxSize - 1) == top; } // 判断空栈 public boolean isEmpty() { return -1 == top; } // 入栈操作 public void push(char c) { if (!this.isFull()) { charArray[++top] = c; System.out.println(c+" 入栈!!!"); } else { System.out.println("栈已满!!!"); } } // 出栈操作 public char pop() throws Exception { if (this.isEmpty()) { throw new Exception(); } else { System.out.println(charArray[top]+" 出栈!!!"); return charArray[top--]; } } // 获取但不出栈 public char peek() throws Exception { if (this.isEmpty()) { throw new Exception(); } else { return charArray[top]; } } }
public class CharChecker { private String input; public CharChecker(String input) { this.input = input; } // 字符串括号语法校验 public void check() { int maxSize = this.input.length(); CheckCharStack stack = new CheckCharStack(maxSize); for (int i = 0; i < maxSize; i++) { char c = input.charAt(i); switch (c) { // 如果为左括号,入栈 case '(': case '[': case '{': stack.push(c); break; // 如果为右括号,出栈一个用来比较 case ')': case ']': case '}': char ch = 0; System.out.println("当前右括号为 "+c); if (!stack.isEmpty()) { try { ch = stack.pop(); } catch (Exception e) { e.printStackTrace(); } // 如果取出的左括号与当前的右括号不对应,则报错 if (('(' == ch && ')' != c) || ('[' == ch && ']' != c) || ('{' == ch && '}' != c)) { System.out.println("Error:" + c + " at " + i + "!!!"); return; } } else { // 如果栈已空,则报错 System.out.println("Error:" + c + " at " + i + "!!!"); return; } break; default: break; } } } //运行 public static void main(String[] args) { new CharChecker("a{b[c])d}").check(); new CharChecker("a{b[c]d}").check(); } }
输出:
{ 入栈!!! [ 入栈!!! 当前右括号为 ] [ 出栈!!! 当前右括号为 ) { 出栈!!! Error:) at 6!!! { 入栈!!! [ 入栈!!! 当前右括号为 ] [ 出栈!!! 当前右括号为 } { 出栈!!!
2.队列
后进后出.
数组和链表常用来实现队列.
插入和取出时间复杂度为O(1).
以数组模拟队列为例,插入时,先移动再赋值,尾部向右移动,当尾部位置为maxSize-1时,需要将尾部位置赋值-1,而下一次则在0的位置插入.
删除时,头部向右移动,先取值再移动,如果移动后的值为maxSize,需要将头部赋值为0,下一次取0的位置的值.
同时需要记录当前元素的数目.(其实队列可以理解为一个环形结构)
代码:用数组模拟队列结构
public class QueueDemo { private int maxSize; //队列长度 private int curNum; //当前元素个数 private int front; //队列头部 private int rear; //队列尾部 private long[] queue; public QueueDemo(int maxSize){ this.maxSize = maxSize; this.curNum = 0; //取出时,头部右移,先取后移,头部初始置于0 this.front = 0; //插入时,尾部右移,先移后插,尾部置于-1 this.rear = -1; this.queue = new long[maxSize]; } //插入 public void insert(long data){ if(this.isFull()){ System.out.println("队列已满!!!"); return; } //如果尾部已经在最后一个,将尾部置为-1 if(this.rear == maxSize-1){ this.rear = -1; } queue[++rear] = data; this.curNum++; System.out.println("数据"+data+"被插入队列,位置为"+this.rear); } //取出(删除) public long remove() throws Exception{ //如果队列为空,抛出异常 if(this.isEmpty()){ throw new Exception("队列为空!!!"); } long result = queue[front++]; this.curNum--; System.out.println("数据"+result+"被取出,从位置"+(this.front-1)); if(maxSize == front){ front = 0; } return result; } //只获取不删除 public long peek(){ return queue[front]; } //判断是否为空 public boolean isEmpty(){ return 0 == curNum; } //判断是否已满 public boolean isFull(){ return curNum == maxSize; } //获取当前元素个数 public int size(){ return curNum; } public static void main(String[] args) throws Exception { QueueDemo queue = new QueueDemo(5); queue.insert(10); queue.insert(20); queue.insert(30); queue.insert(40); queue.remove(); queue.remove(); queue.remove(); queue.insert(10); queue.insert(20); queue.insert(30); queue.insert(40); queue.insert(50); queue.remove(); queue.remove(); queue.remove(); queue.remove(); queue.remove(); queue.remove(); } }
输出:
数据10被插入队列,位置为0 数据20被插入队列,位置为1 数据30被插入队列,位置为2 数据40被插入队列,位置为3 数据10被取出,从位置0 数据20被取出,从位置1 数据30被取出,从位置2 数据10被插入队列,位置为4 数据20被插入队列,位置为0 数据30被插入队列,位置为1 数据40被插入队列,位置为2 队列已满!!! 数据40被取出,从位置3 数据10被取出,从位置4 数据20被取出,从位置0 数据30被取出,从位置1 数据40被取出,从位置2 Exception in thread "main" java.lang.Exception: 队列为空!!! at queue.QueueDemo.remove(QueueDemo.java:39) at queue.QueueDemo.main(QueueDemo.java:92)
双端队列简介
一种多用途的数据机构,左右两边都可以进行插入和取出操作,需要定义以下四种方法.
insertLeft()
insertRight()
removeLeft()
removeRight()
双端队列可以通过禁用部分功能,同时做栈和队列使用.
禁用insertLeft(),removeLeft()可以作栈使用.
禁用insertLeft(),removeRight()可以作一般队列使用.
3.优先级队列
插入队列的数据有优先级的高低,优先级高的将被先取出.通常使用堆来实现优先级队列,此处暂时用数组模拟.如果将数据的值作为优先级,值越大则越先被取出.
通常将值最小的固定数组角标的0的位置,后续插入的数将进行排序和移动,取出始终取值最大的.
优先级队列的时间复杂度:插入O(N),删除O(1).
代码:数组模拟优先级队列
public class PriorityQueueDemo { private int curIndex; private long[] queueArray; private int maxSize; public PriorityQueueDemo(int maxSize) { this.maxSize = maxSize; this.queueArray = new long[maxSize]; this.curIndex = -1; } // 插入,每次插入需要查找遍历应该插入的位置 public void push(long data) { if (this.curIndex == this.maxSize - 1) { System.out.println("队列已满!!!"); return; } System.out.println("元素" + data + "被插入!!!"); if (this.curIndex == -1) { queueArray[++this.curIndex] = data; } else { // 从数组尾部开始比较,如果data<=queue[i],将queue[i]右移一位 for (int i = this.curIndex; i >= 0; i--) { if (data <= queueArray[i]) { queueArray[i + 1] = queueArray[i]; if(i == 0){ queueArray[0] = data; } } else { // 如果data>queue[i],将data填入queue[i+1] queueArray[i + 1] = data; break; } } ++this.curIndex; } } // 取出元素 public long pop() throws Exception { if (curIndex == -1) { throw new Exception("队列为空!!!"); } else { System.out.println("元素" + this.queueArray[this.curIndex] + "被取出"); return this.queueArray[this.curIndex--]; } } // 获取元素值 public long peek() throws Exception { if (curIndex == -1) { throw new Exception("队列为空"); } else { return this.queueArray[this.curIndex]; } } // 是否已满 public boolean isFull() { return (maxSize - 1) == this.curIndex; } // 是否为空 public boolean isEmpty() { return -1 == this.curIndex; } public static void main(String[] args) throws Exception { PriorityQueueDemo queue = new PriorityQueueDemo(5); queue.push(20); queue.push(30); queue.push(10); queue.push(35); queue.push(5); while (!queue.isEmpty()) { queue.pop(); } } }
输出:
元素20被插入!!! 元素30被插入!!! 元素10被插入!!! 元素35被插入!!! 元素5被插入!!! 元素35被取出 元素30被取出 元素20被取出 元素10被取出 元素5被取出
相关文章推荐
- Python cookbook(数据结构与算法)实现优先级队列的方法示例
- [数据结构与算法]堆与优先级队列
- 《数据结构与算法》学习笔记11 优先级队列
- 数据结构与算法(Java描述)-10、链式队列以及优先级队列的应用
- JavaScript数据结构与算法(三) 优先级队列的实现
- C语言实现优先级队列——priqueue
- 优先级队列优化的霍夫曼编码(带中文压缩)
- 【数据结构】用模版实现大小堆、实现优先级队列,以及堆排序
- [置顶] 优先级队列及小顶堆排序
- [数据结构] 二叉堆,堆排序,优先级队列
- 【Java数据结构学习笔记之三】Java数据结构与算法之队列(Queue)实现
- 堆和堆排序(堆实现优先级队列)
- 浅谈算法和数据结构: 五 优先级队列与堆排序
- C# 数据结构与算法系列(五) 队列
- 利用redis实现带优先级的消息队列
- [数据结构]用插入排序和选择排序的思想实现优先级队列
- HYSBZ 1216 操作系统 优先级队列的应用
- 优先级队列:PriorityQueue
- Linux下使用hiredis库实现优先级队列
- java集合——队列和双端队列+优先级队列