堆栈
栈(stack)又名堆栈,它是一种先进后出(FILO)的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
堆栈的数组存储
由一个一维数组和一个记录栈顶元素位置top的变量组成
元素插入数组的最后,所以top指向数组元素的最后位置。
删除只要将top往前移动一位。继续插入的话,top后面有元素只需覆盖它就行。直到数组满了。
代码
public class Mystack {
private int[] stack;
private int top = -1;
public Mystack() {
stack = new int [10]; //设定栈大小为10,栈空间中存放int类型
}
public void push(int a) { //插入元素
if(top < 9)
stack[++top] = a;
else
System.out.print("满了");
}
public boolean isempty() {
return top == -1;
}
public int peek() { //拿到栈顶元素
if(isempty())
return -9999;
return stack[top];
}
public int pop() { //删除栈顶元素
if(isempty())
return -9999;
int a = peek();
top--;
return a;
}
例子‘’
用一个数组来实现俩个堆栈,最大程度的利用空间
只需堆栈总=从数组的俩端开始插入,直到俩个堆栈的top相邻,这样数组就满了。
堆栈的链表存储
堆栈的链表存储,就是一个单链表。指向栈顶元素的top一直 指向了链表的头部。
代码
public class Mystacknode {
public class Node{
private Object data;
private Node next;
public Node(Object data){
this.data=data;
}
}
Node top = null;
public boolean isempty() {
return top ==null;
}
public void push(int a) {
Node node = new Node(a);
node.next = top;
top = node;
}
public Object peek() {
return top.data;
}
public Object pop() {
if(isempty())
return null;
Object a = top.data;
top = top.next ;
return a;
}
队列
- 队列(Queue):是具有一定操作约束的线性表
-只能在一端插入,另一端删除
-先进先出
队列的数组存储
由一个一维数组和一个记录队列头元素的位置front和一个记录队列尾位置的rear组成。
普通数组存储
首先,队列为空时,front和rear指向-1的位置,push进来一个元素,rear++,删除一个元素,front++,所以front一直是指向头元素的前一个位置,rear指向尾元素。(缺点,如果插入删除操作重复,数组前面的空间会浪费)
顺坏队列
当变量rear一直到数组的尾端时,继续进行插入操作时,可以回到数组的头继续插入,前提是数组的头部分空间已经给空了。(缺点在顺坏队列中,队列中的元素个数是通过front和rear的相对值来确定的,但是判断队列是否为空,是否为满的条件都是front == rear。
)
解决方案
(1)使用额外的标记,记录最后一次是删除操作还是插入操作。当条件是front == rear时,查看标记,就可以知道队列是满还是空
(2)仅使用n-1个数组空间,这样的话条件是front == rear时,队列是空的,(rear+1) % queue.length == front时,队列为满
代码
public class Myqueue {
private int[] queue;
private int front,rear;
public Myqueue() {
queue = new int[10]; //建立大小为10的数组作为队列,里面放9个元素
front = -1; //front一直指向队列头元素的前一个位置
rear = -1;
}
public boolean isempty() {
return front == rear;
}
public boolean isfull() {
return (rear+1) % queue.length == front;
}
public void put(int a) {
if(isfull())
System.out.print("队列满了");
queue[(rear+1) % queue.length ] = a; //取余 才能完成顺坏的循环
rear = (rear+1) % queue.length ;
}
public int pop() {
if(isempty())
System.out.print("队列空的");
int a = queue[(front+1)%queue.length];
front = (front+1)%queue.length;
return a;
}
队列的链式存储
- front指向队列头结点
- rear指向队列尾结点
代码
public class MyqueueList {
public class Node{
private Object data;
private Node next;
public Node(Object data){
this.data=data;
}
}
Node front = null;
Node rear = null;
public boolean isempty() {
return front == null;
}
//入队
public void put(Object e) {
Node node = new Node(e);
if(isempty()) {
front = node;
rear = node;
}
rear.next = node;
rear = node;
}
//出队
public Object pop() {
if(isempty())
System.out.print("队列为空");
Object a = front.data ;
front = front.next ;
return a;
}
public int size() {
if(isempty())
return 0;
Node curr = front;
int a= 0;
while(curr != null) {
curr = curr .next ;
a++;
}
return a;
}