队列
队列(queue) 是只允许在一端进行插入操作,而在另一端进行删除操作的线性表
队列是一种先进先出的线性表,简称FOIO。允许插入一端称为队尾,允许删除的一端称为队头。队列符合我们的生活习惯例如排队,排在第一个的优先出列,最后来的只能插入到队伍最末尾。
我们假设一个队列有n个元素,则顺序存储的队列需建立一个大于m的数组,并把队列的所有元素存储在数组的前n个单元,数组下标为0的一端即是队头。所滑的入队列操作,其实就是在队尾追加一个元素,不需要移动任何元素,因此时间复杂度为O(1)。队列元素的出列是在队头,即下标为0的位置,那也就意味着,队人列中的所有元素都得向前移动,以保证队列的队头,也就是下标为0的位置不为空,此时时间复杂度为O(n);
下面用数组模拟实现队列:
package com.jxust.queue;
import java.util.Scanner;
public class ArrayQueueDemo {
public static void main(String[] args) {
ArratQueue queue=new ArratQueue(3);
Scanner choice=new Scanner(System.in);
while (true){
System.out.println("1:显示队列");
System.out.println("2.添加数据");
System.out.println("3.取出数据");
System.out.println("4.查看队列头");
System.out.println("5.退出");
int key=choice.nextInt();
switch (key){
case 1:
queue.show();
break;
case 2:
System.out.println("输入一个数");
int d=choice.nextInt();
queue.add(d);
break;
case 3:
try {
int d1=queue.get();
System.out.println("取出的数为"+d1);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 4:
try {
int d2= queue.head();
System.out.println("队列头是"+d2);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case 5:
queue.exit();
break;
default:
break;
}
}
}
}
class ArratQueue {
private int maxSize;//表示数组的最大容量
private int front;//队列头,队列头前一个位置(不是队列第一个元素)
private int rear;//队列尾(队尾最后一个数据)
private int [] arr ;//该数据用于存放数据
public ArratQueue(int arrMaxSize){
maxSize=arrMaxSize;
arr =new int [maxSize];
front=-1;//指向队列头部
rear=-1;//指向队列尾
}
//判断队列是否满
public boolean isFull(){
return rear==maxSize-1;
}
//判断队列是否为空
public boolean isEmpty(){
return rear==front;
}
//添加数据到队列
public void add(int n){
if(isFull()) {
System.out.println("队列已满 不能加入");
return;
}
rear++;
arr[rear]=n;
}
public int get(){
if(isEmpty()){
throw new RuntimeException("队列空,不能取数据");
}
front++;
return arr[front];
}
//显示队列所有数据
public void show(){
if (isEmpty()){
System.out.println("队列空");return;
}
for (int i = 0; i <arr.length ; i++) {
System.out.printf("arr[%d]=%d\n",i,arr[i]);
}
// for (int i = front; i!=rear+1 ; i++) {
// System.out.printf("arr[%d]=%d\n",i,arr[i]);
// }
}
public int head(){
if (isEmpty()){
throw new RuntimeException("队列空");
}
return arr[front+1];
}
public void exit(){
System.exit(0);
}
}
循环队列
为了解决假溢出的办法很简单,就是后面满了,就再从头开始,也就是头尾相连的循环。我们把队列的这种头尾相连的顺序存储结构称为循环队列。
下面代码实现循环队列:
package com.jxust.queue;
import java.util.Scanner;
public class CircleArrayDeom {
public static void main(String[] args) {
CircleArray ca = new CircleArray(4);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("输入1,显示队列");
System.out.println("输入2,加入数据");
System.out.println("输入3,取出数据");
System.out.println("输入4,显示头数据");
int input = sc.nextInt();
switch (input) {
case 1:
ca.show();
break;
case 2:
System.out.println("输入你所要加入的数字");
int addnum = sc.nextInt();
ca.add(addnum);
break;
case 3:
System.out.println("你取出的数为" + ca.get());
case 4:
System.out.println("头数据为" + ca.head());
break;
default:
break;
}
}
}
}
class CircleArray {
private int maxSize;//表示数组的最大容量
private int front = 0;//队列头
private int rear = 0;//队列尾(队尾最后一个数据)
private int[] arr;//该数据用于存放数据
public CircleArray(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
}
//判断队列是否满
public boolean isFull() {
return (rear+1)%maxSize == front;
}
//判断队列是否为空
public boolean isEmpty() {
return rear==front;
}
//添加数据到队列
public void add(int n) {
if (isFull()) {
System.out.println("队列已满 不能加入");
return;
}
arr[rear] = n;
rear = (rear + 1) % maxSize;
}
public int get() {
if (isEmpty()) {
throw new RuntimeException("队列空,不能取数据");
}
int valuer = arr[front];
front = (front + 1) % maxSize;
return valuer;
}
//显示队列所有数据
public void show() {
if (isEmpty()) {
System.out.println("队列空");
return;
}
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
}
// for (int i = front; i!=rear+1 ; i++) {
// System.out.printf("arr[%d]=%d\n",i,arr[i]);
// }
}
public int size() {
return (rear + maxSize - front) % maxSize;
}
public int head() {
if (isEmpty()) {
throw new RuntimeException("队列空");
}
return arr[front];
}
public void exit() {
System.exit(0);
}
}
栈练习题
输入样例:
10 push 5 query push 6 pop query pop empty push 4 query empty
输出样例:
5 5 YES 4 NO
#include<iostream>
using namespace std;
const int N=100010;
int m;
int stk[N],tt;
int main(){
cin>>m;
while (m--){
string c; int x;
cin>>c;
if(c=="push") { cin>>x; stk[++tt]=x;}
else if(c=="pop"){ tt--;}
else if(c=="empty") cout<<(tt ? "NO":"YES")<<endl;
else cout<<stk[tt]<<endl;
}
return 0;
}
输入样例:
(2+2)*(1+1)
输出样例:
8
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<unordered_map>
using namespace std;
stack<int> num;//栈
stack<char> op;
void eval()
{
auto b = num.top(); num.pop();
auto a = num.top(); num.pop();
auto c = op.top(); op.pop();
int x;
if (c == '+') x = a + b;
else if (c == '-') x = a - b;
else if (c == '*') x = a * b;
else x = a / b;
num.push(x);
}
int main(){
unordered_map<char,int> pr{{'+',1},{'-',1},{'*',2},{'/',2} };
string str;
cin>>str;
for(int i=0;i<str.size();i++)
{
auto c=str[i];
if(isdigit(c)){ //isdigit()函数判断当前输入的字符串是否是由数字组成
int x=0,j=i;
while(j<str.size()&&isdigit(str[j]))
x=x*10+str[j++]-'0';
num.push(x);
i=j-1;
}
else if(c=='(' )op.push(c);
else if(c==')'){
while(op.top() != '(' ) eval();
op.pop();
}
else{
while(op.size()&&pr[op.top()]>=pr[c]) eval();
op.push(c);
}
}
while(op.size()) eval();
cout<<num.top()<<endl;
return 0;
}