栈的设计
设计思路:
栈是 线性表的 特例→线性表是用数组来实现的→用数组来实现栈
设计方法:
1、使下标为0的一端来作为栈底;
2、定义top下标:指示栈顶元素在数组中的位置【top=-1表示栈空,top=stackSize-1,表示栈满(stackSize是栈的容量)】
主要实现的三个方法:
1、压栈:push(int x)
2、弹栈:pop()
3、查看栈顶元素 peek()
实现代码:
package use_stack;
public class Mystack {
private int top;
private int []array;
private int stackSize;
public Mystack(int k){//设置容量数组容量k
this.top=-1;//栈空时,top=-1
this.array=new int [k];
this.stackSize=k;
}
public boolean push(int e){
if(top==stackSize-1){
return false;
}
top++;
array[top]=e;
return true;
}
public int pop(){
if(isEmpty()){
throw new ArrayIndexOutOfBoundsException();
}
int ret=array[top--];
return ret;
}
public int peek(){
if(isEmpty()){
throw new ArrayIndexOutOfBoundsException();
}
return array[top];
}
public boolean isEmpty(){
return top==-1;
}
}
设计实现链表结构的队列
采用单链表结构实现队列,因为如果用数组实现,做头删操作是比较复杂。
设计步骤:
1、设定两个引用front、rear,以及记录链表长度的size变量;
2、入队:offer(int x):【判断链表是否为空】;size++;
3、出队:poll():【判断链表是否为空】;size–;
4、检索队头元素:peek():【判断链表是否为空】;
5、实时返回链表长度:size();
实现队列代码:
public class MyQueue {
private Node front;
private Node rear;
private int size ;
//初始化
public MyQueue(){
front=null;
rear=null;
this.size=0;
}
//入队
public void offer(int x){
Node node=new Node(x);
if(size==0){
front=node;
rear=node;
}
else{
rear.next=node;
rear=node;
}
size++;
}
//出队
public int poll(){
if(size==0){
throw new RuntimeException("队列为空");
}
Node oldFront=front;
front=front.next;
if(front==null){
rear=null;
}
size--;
return oldFront.val;
}
//检索队头元素
public int peek(){
if(size==0){
throw new RuntimeException("队列为空");
}
return front.val;
}
//判断是否为空
public boolean isEmpty(){
return size==0;
}
//实时记录链表长度
public int size(){
return size;
}
}
设计实现循环队列
设计思路:
设计顺序存储的队列不能充分利用空间,所以设计循环队列
1、引入两个指针,front指向队头元素,rear指向队尾元素的下一个位置
2、此时,如何判断是“空队列”or“满队列”?
方法:*当front=rear时,队空
当(rear+1)%QueueSize==front时,队满。
3、数组下标循环技巧:a、下标最后再往后:(rear+1)%QueueSize
b、下标最前再往前:(front-1+QueueSize)%QueueSize
实现循环队列代码:
//实现循环队列
public class MyCircularQueue {
private int []array;
private int frontIndex;
private int rearIndex;
private int size;
public MyCircularQueue(int k) {
array=new int [k+1];//数组容量是k,但是,得保留一个空闲元素空间给rear,所以空间多设置一位
frontIndex=0;
rearIndex=0;
size=0;
}
//向循环队列插入一个元素。如果成功插入则返回真。
public boolean enQueue(int value) {
//如果队列已满,返回false;
if(isFull()){
return false;
}
array[rearIndex]=value;
rearIndex=(rearIndex+1)%array.length;
size++;
return true;
}
//从循环队列中删除一个元素。如果成功删除则返回真。
public boolean deQueue() {
if(isEmpty()){
return false;
}
//front指针向后移动一位,若到最后则转向数组头部
frontIndex=(frontIndex+1)%array.length;
size--;
return true;
}
// 从队首获取元素。如果队列为空,返回 -1 。
public int Front() {
if(isEmpty()){
return -1;
}
return array[frontIndex];
}
//获取队尾元素。如果队列为空,返回 -1 。
public int Rear() {
if(isEmpty()){
return -1;
}
int index=(rearIndex-1+array.length)%array.length;
return array[index];
}
//检查循环队列是否为空。
public boolean isEmpty() {
return frontIndex==rearIndex;
}
//检查循环队列是否已满。
public boolean isFull() {
return (rearIndex+1)%array.length==frontIndex;
}
}