目录
3.栈
(1)定义
栈是一种只能在一端进行插入或删除操作的线性表,因此根据存储结构的不同分为顺序栈和链栈。其中允许进行插入或删除操作的一端称为栈顶(top),栈顶由一个称为栈顶指针的位置指示器来指示,它是动态变化的。表的另一端称为栈底,栈底是固定不变的。栈的插入和删除操作一般称为入栈(push)和出栈(pop)。栈最主要的特点就是先进先出。
(2)声明一个顺序栈
/**
* 顺序栈
*/
public class SqStack<T> {
private Object[] elementsData;//所有元素数据
private int top;//栈顶指针(索引)
//构造方法
public SqStack(int capacity) {//规定栈的容量
if (capacity < 1) throw new IllegalArgumentException();
elementsData = new Object[capacity];
top = -1;
}
//入栈
public void push(T data){
if(top==elementsData.length-1){
System.out.println("栈已满");
return;
}
elementsData[++top] = data;//入栈操作
}
//出栈
public T pop(){
if(top==-1){
System.out.println("栈已空");
return null;
}
return (T)elementsData[top--];//出栈操作
}
}
(3)声明一个链栈
/**
* 链栈
*/
public class LinkStack<E> {
/**
* 声明链栈结点
*/
private class LNode{
private E data;//结点数据
private LNode next;//结点的后继结点地址
//构造方法
private LNode(){}
}
private LNode top;//栈顶指针
public LinkStack(){//链栈随机开辟内存空间,不会栈满
}
//入栈:头插法
public void push(E data){
LNode lNode = new LNode();//申请新结点
lNode.data = data;
lNode.next = top;
top = lNode;
}
//出栈
public E pop(){
if(top==null){
System.out.println("栈已空");
return null;
}
E temp = top.data;
top = top.next;
return temp;
}
}
4.队列
(1)定义
队列同栈一样,也是一种操作受限的线性表,其被限制为仅允许在表的一端进行插入,在表的另一端进行删除。可进行插入的一端称为队尾(rear),可进行删除的一端称为队头(front)。向队尾插入元素称为入队(enQueue),从队头删除元素称为出队(deQueue)。队列的主要特点是先进先出。
(2)声明一个顺序循环队列
假溢出:在顺序队中,元素入队rear指针向后移,元素出队front指针向后移,经过一系列操作之后,两个指针可能同时指向数组末尾。此时虽然队列为空,但却无法让元素入队,这就是所谓的假溢出。
那么假溢出应该如何解决呢?此时可以把数组在逻辑上变成一个环,这样就不会出现假溢出的情况。但此时又出现了一个新的问题,元素空与满的时候,均是两个指针重合,因此只能损失一个空间,使得空的时候指针重合,满的时候指针间隔一个空元素,这样就完美解决了假溢出的问题。
/**
* 顺序循环队列
*/
public class SqQueue<E> {
private Object[] elemnetsData;//所有元素数据
private int front;//队头
private int rear;//队尾
//构造方法
public SqQueue(int capacity) {
if (capacity < 1) throw new IllegalArgumentException();
//循环队列浪费一个空间
elemnetsData = new Object[capacity + 1];
}
//入队
public void enQueue(E data) {
if ((rear + 1) % elemnetsData.length == front) {
System.out.println("队列已满");
return;
}
rear = (rear + 1) % elemnetsData.length;//尾指针后移
elemnetsData[rear] = data;
}
//出队
public E deQueue() {
if (rear == front) {
System.out.println("队列已空");
return null;
}
front = (front + 1) % elemnetsData.length;//头指针后移
E temp = (E) elemnetsData[front];
elemnetsData[front] = null;
return temp;
}
}
(3)声明一个链队
/**
* 链队
*/
public class LinkQueue<E> {
/**
* 声明链队的结点
*/
private class LNode {
private E data;//结点数据
private LNode next;//结点的后继结点地址
//构造方法
private LNode() {
}
}
private LNode front;//头指针
private LNode rear;//尾指针
//构造方法
public LinkQueue() {
}
//入队:头插法
public void enQueue(E data) {
LNode lNode = new LNode();
lNode.data = data;
//队列为空时需要特殊处理
if (rear == null) {
rear = lNode;
front = lNode;
}
rear.next = lNode;
rear = lNode;
}
//出队
public E deQueue() {
if (rear == null) {
System.out.println("队列已空");
return null;
}
E temp = front.data;
front = front.next;//队头指针后移
//队列为空时需要特殊处理
if (front == null) rear = null;
return temp;
}
}