(一)栈的定义
示意图:
栈:是一种只能在一端插入或删除操作的线性表
栈的几个重要概念:
- 运行进行插入、删除操作的一端称为栈顶
- 表的另一端称为栈底
- 当栈中没有元素时,称为空栈
- 栈中插入元素称为入栈
- 栈中删除元素称为出栈
栈的主要特点:先进后出,既后进的元素先出栈。
(二)栈的代码实现
栈的实现方式有2种:静态栈--数组实现 动态栈--链表实现
1.静态栈--数组实现
从顺序栈示意图中我们可以看到栈的顺序存储结构可以使用一个数组+一个top整形变量来实现,利用数组来顺序存储栈中的所有元素,利用top整形变量来表示栈顶元素的下标位置。
规定:
- top总是指向栈顶元素,初始值为-1
- 当top == MaxSize-1时,表示栈满了,不能再进栈
- 进栈top加1,出栈top减1
顺序栈4要素:
- 栈空条件:top = -1
- 栈满条件:top == MaxSize-1
- 进栈操作:++top
- 出栈操作:top--
静态栈--数组实现代码演示
class ArrayStack<T> {
//数组保存数据
private Object[] data;
//约定top总是指向栈顶元素,初始值为-1
private int top;
/**
* 1.初始化数组大小==初始化栈大小
* @param initArraySize
*/
public ArrayStack(int initArraySize) {
this.top = -1;
data = new Object[initArraySize];
}
/**
* 2.判断栈是否为空
* @return
*/
public boolean isEmpty(){
return top == -1 ? true : false;
}
/**
* 3.入栈
* @param value
*/
public void push(T value) throws Exception {
if(top == data.length-1){
throw new Exception("栈满异常");
}
data[++top] = value;
}
/**
* 4.出栈
* @throws Exception
*/
public T pop()throws Exception{
if(top == -1){
throw new Exception("栈空异常");
}
T t = (T)data[top--];
return t;
}
/**
* 5.遍历栈
*/
public void traverse(){
while (top != -1){
System.out.println(""+data[top--]);
}
}
/**
* 6.获取栈顶元素
* @return
*/
public T getTop(){
return (T) data[top];
}
public static void main(String[] args) throws Exception {
ArrayStack stack = new ArrayStack(4);
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
//获取栈顶元素 = 4
System.out.println("获取栈顶元素 = "+stack.getTop());
for (int i = 0; i <4 ; i++) {
//输出:4 3 2 1
System.out.print( stack.pop()+"\t");
}
}
}
2. 动态栈--链表实现
如果栈中的元素变化范围较大或不清楚栈中的元素数量,这个时候应该想到要使用链式存储结构。链式存储结构表示的栈称为链栈。
链栈4要素:
- 栈空条件:栈顶元素为空,那么栈就为空。a1 == null
- 栈满条件:不考虑,因为链栈可以无限长
- 进栈操作:将包含数据的节点插入头结点的前面
- 出栈操作:取出头结点之后的元素,并把它删除
动态栈--链表实现代码演示
public class StackInList {
//栈顶节点
Node stackTop;
/**
* 1.初始化栈的大小为null
*/
public StackInList(){
stackTop = null;
}
/**
* 2.入栈操作
* @param data
*/
public void push(int data){
//把数据封装成节点
Node newNode = new Node(data);
//新节点插到栈顶的前面
newNode.next= stackTop;
//栈顶指向新节点
stackTop = newNode;
}
/**
* 3.出栈操作
* @return
*/
public int pop() throws Exception {
//判断栈是否为空
if(stackTop==null){
throw new Exception("空栈无数据");
}
//取出栈顶顶元素
int data = stackTop.data;
//栈顶指针指向下一个节点,表示已经把data元素删除了
stackTop=stackTop.next;
return data;
}
/**
* 4.获取栈顶元素
* @return
*/
public int getTop(){
return stackTop.data;
}
/**
* 5.判断栈是否为空
* @return
*/
public boolean isEmpty(){
return stackTop == null ? true:false;
}
static class Node{
//下一个节点
private Node next ;
private int data;
public Node(int date){
this.data = date;
}
}
public static void main(String[] args) throws Exception {
StackInList stack = new StackInList();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println("获取栈顶元素 = "+stack.getTop());
System.out.println("判断栈是否为空 = "+stack.isEmpty());
for (int i = 0; i < 3; i++) {
System.out.println("stack = " + stack.pop());
}
}
}
(三)队列的定义
示意图
队列是限定只能在队头(font)进行删除操作、在队尾(rear)进行插入操作的线性表。队列的主要特点:先进先出--FIFO
队列的几个重要概念
- 把进行插入的一端称作为队尾--rear
- 把进行删除的一端称作为对头--front
- 向队列插入新元素称作为入队,新元素入队后就成了队尾元素
- 从队列中删除元素称作为出队,元素出队后,其后继元素就成了队首元素
(四) 队列的代码实现
队列的实现方式有2中:静态队列--数组实现 动态队列--链表实现
1.静态队列--数组实现
规定:
- 约定rear指向队尾元素
- 元素进队列后,rear加一
- 约定front总是指向当前队中队头元素的前一位置
- 元素出队,front加一
- 当队尾rear == MaxSize-1时不能再进队列
顺序队列的5要素:
- 初始化时: front = rear = -1
- 队空条件: front = rear
- 队满条件: rear = MaxSize-1
- 入队条件: rear++ data[rear] =e 或 data[++rear] = e
- 出队条件: front++ e = data[front] 或 e = data[++front]
静态队列--数组代码实现
public class Queue {
private Object[] data;
//队头指针
private int front = -1 ;
//队尾指针
private int rear = -1;
public QueueArray2(int size) {
data = new Object[size];
}
/**
* 入队
* @param value
*/
public void putElem(Object value) throws Exception {
if(rear == data.length -1){
throw new Exception("队列已满异常");
}
rear++;
data[rear] = value;
}
/**
* 出队
*/
public Object popElemt() throws Exception {
if(isEmpty()){
throw new Exception("空队列异常");
}
front ++ ;
return data[front];
}
/**
* 是否为空队列
* @return
*/
public boolean isEmpty(){
return front == rear;
}
/**
* 遍历队
*/
public void traverse(){
for(int i = 0; i < data.length; i++){
System.out.print("\t"+data[i]);
}
}
public static void main(String[] args) throws Exception {
QueueArray2 queue = new QueueArray2(3);
queue.putElem(1);
queue.putElem(2);
queue.putElem(3);
queue.traverse();
queue.popElemt();
queue.popElemt();
queue.popElemt();
System.out.println(queue.isEmpty());
}
}
2. 动态队列--链表实现
链队列4要素:
- 队列为空的条件:front == null
- 队列满条件:不考虑,因为链队列可以无限长
- 进队操作条件:如果front == null表明队列为空,front = newNode rear = newNode ,如果队列不为null,rear指针往后移动
- 出队操作条件:如果front == null表明队列为空,不操作,否则front指针向后移动
动态队列--链表实现代码演示
public class Queue {
//1.队列头结点
private Node font;
//2.队列尾结点
private Node rear;
/**
* 入队
* @param data
*/
public void putElem(int data){
//3.添加一个新节点封装数据
Node newNode = new Node(data);
//4.判断队列是否为空队列
if (font == null){
//5.队列头结点和尾结点指向同一个newNode
rear = newNode;
font = newNode;
}else {
//6.rear指向下一个newNode
rear.next = newNode;
rear=rear.next;
}
}
/**
* 出队
* @return
* @throws Exception
*/
public int popElem() throws Exception {
//1.判断队列是否为空队列
if (font == null){
throw new Exception("已是空队列");
}
//2.获取结点数据
int data = font.data;
font = font.next;
return data;
}
static class Node{
private int data;
private Node next;
public Node(int data){
this.data = data;
}
}
public static void main(String[] args) throws Exception {
Queue queue = new Queue();
queue.putElem(1);
queue.putElem(2);
queue.putElem(3);
for (int i = 0; i < 3 ; i++) {
System.out.print(queue.popElem()+"\t");
}
}
}