一、 栈
1、概念
栈是一种特殊的线性表,它只能在栈顶(top)进行插入(push)和删除(pop)操作。
栈的常用操作:
入栈(push):向栈顶插入元素
出栈(pop):从栈顶删除元素
访问栈顶元素(peek):访问栈顶元素
2、 栈的顺序结构的实现
public class SequenceStack<T> {
private Object[] elementData; //数组用于承装元素
private int DEFAULT_SIZE = 20; //初始数组默认大小
private int capacity;
private int capacityIncrement = 5;
private int size = 0; <span style="color:#009900;">//栈中当前容量
</span> public SequenceStack(){
capacity = DEFAULT_SIZE;
elementData = new Object[capacity];
}
public SequenceStack(T element){
this();
elementData[0] = element;
size++;
}
public int length(){ <span style="font-family: Arial, Helvetica, sans-serif;">//返回栈的长度</span></span>
return this.size;
}
<span style="color:#009900;">//入栈操作</span>
public void push(T element){
this.ensureCapacity();
elementData[size] = element;
size++;
}
<span style="color:#009900;">//出栈操作</span>
public T pop(){
T popElement = (T)elementData[size-1];
size--;
return popElement;
}
<span style="color:#009900;">//访问栈顶元素</span>
public T peek(){
return (T)elementData[size-1];
}
<span style="color:#009900;">//判断是否为空</span>
public boolean isEmpty(){
boolean b = false;
if(size == 0){
b = true;
}
return b;
}
<span style="color:#009900;">//清空栈</span>
public void clear(){
for(Object o:elementData){
o = null;
}
size = 0;
}
<span style="color:#009900;">//遍历栈</span>
public void view(){
System.out.print("当前栈中元素为:");
for(int i = 0;i < size;i++){
System.out.print(elementData[i] + " ");
}
System.out.println();
}
<span style="color:#009900;">//栈容量检测与扩充</span>
public void ensureCapacity(){
if(capacityIncrement > 0){
while((size+1) > capacity){
capacity+=capacityIncrement;
}
}
else{
while((size+1) > capacity){
capacity = capacity * 2;
}
}
}
public static void main(String[] args) {
SequenceStack<String> sequenceStack = new SequenceStack<> ();
sequenceStack.push("hello");
sequenceStack.push("world");
sequenceStack.push("perfect");
System.out.print("入栈操作后,");
sequenceStack.view();
sequenceStack.pop();
System.out.print("出栈操作后,");
sequenceStack.view();
System.out.println("当前栈顶元素为:" + sequenceStack.peek());
sequenceStack.clear();
System.out.println("clear之后,栈是否为空:" + sequenceStack.isEmpty());
}
}
3、栈的链式结构的实现:
public class LinkedStack<T> {
private class Node{
private T data;
private Node next;
public Node(){
}
public Node(T element,Node next){
this.data = element;
this.next = next;
}
}
private Node top;
private int size = 0;
public LinkedStack(){
}
public LinkedStack(T element){
top = new Node(element,null);
size++;
}
//获取栈大小
public int length(){
return size;
}
//入栈操作
public void push(T element){
Node newNode;
newNode = new Node(element, top);
top = newNode;
size++;
}
//出栈操作
public T pop(){
Node oldNode = top;
top = top.next;
oldNode.next = null;
size--;
return oldNode.data;
}
//获取栈顶元素
public T peek(){
return top.data;
}
//清空栈
public void clear(){
top = null;
size = 0;
}
public boolean isEmpty(){
if(size == 0){
return true;
}
return false;
}
//遍历栈中元素
public void view(){
Node currentNode = top;
System.out.print("栈中元素为:");
while(currentNode != null){
System.out.print(currentNode.data + " ");
currentNode = currentNode.next;
}
System.out.println();
}
public static void main(String[] args) {
LinkedStack<String> linkedStack = new LinkedStack<>();
linkedStack.push("hello");
linkedStack.push("world");
linkedStack.push("perfect");
System.out.print("入栈操作后,");
linkedStack.view();
linkedStack.pop();
System.out.print("出栈操作后,");
linkedStack.view();
System.out.println("当前栈顶元素为:" + linkedStack.peek());
linkedStack.clear();
System.out.println("clear之后,栈是否为空:" + linkedStack.isEmpty());
}
}
二、 队列
1、概念
队列是一种被限制的线性表,它只允许在表的前端(front,即队尾)进行删除操作,只允许在表的后端(rear,即队头)进行插入操作
常用操作:
加入元素:向队列rear端插入元素
删除元素:从队列的front端删除元素
访问队列front端元素:
2、队列的顺序存储结构及实现
public class SequenceQueue<T> {
private int DEFAULT_SIZE = 20;
private int capacity;
private int front = 0;
private int rear = 0;
private Object[] elementData;
public SequenceQueue(){
capacity = DEFAULT_SIZE;
elementData = new Object[capacity];
}
public SequenceQueue(T element){
this();
elementData[0] = element;
rear++;
}
<span style="color:#009900;">// 获取队列长度</span>
public int length(){
return rear-front;
}
<span style="color:#009900;">//向队列尾添加元素</span>
public void add(T element){
if(rear > capacity-1){
throw new IndexOutOfBoundsException("队列已满");
}
elementData[rear++] = element;
}
<span style="color:#009900;">//删除队列头元素</span>
public T remove(){
if((rear-front) == 0){
throw new IndexOutOfBoundsException("队列为空,不能删除");
}
T remove = (T)elementData[front];
elementData[front++] = null;
return remove;
}
<span style="color:#009900;">//获取队列头部元素</span>
public T getElement(){
return (T)elementData[front];
}
<span style="color:#009900;">//判断队列是否为空</span>
public boolean isEmpty(){
return (rear-front) == 0;
}
<span style="color:#009900;">//清空队列</span>
public void clear(){
Arrays.fill(elementData, null);
front = 0;
rear = 0;
}
<span style="color:#009900;">//遍历队列</span>
public void view(){
System.out.print("队列中元素为:");
for(int i = front;i < rear; i++){
System.out.print(elementData[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
SequenceQueue<String> sequenceQueue = new SequenceQueue<> ();
sequenceQueue.add("hello");
sequenceQueue.add("world");
sequenceQueue.add("perfect");
sequenceQueue.view();
System.out.println("执行remove删除的元素为:" + sequenceQueue.remove());
System.out.println("队列头部元素为:" + sequenceQueue.getElement());
sequenceQueue.clear();
System.out.println("clear之后队列长度:" + sequenceQueue.length());
}
}
3、顺序存储结构的循环队列
public class LoopSequenceQueue<T> {
private int DEFAULT_SIZE = 5;
private int capacity;
private int front = 0;
private int rear = 0;
private Object[] elementData;
public LoopSequenceQueue(){
capacity = DEFAULT_SIZE;
elementData = new Object[capacity];
}
public LoopSequenceQueue(T element){
this();
elementData[0] = element;
rear++;
}
<span style="color:#009900;">//获取队列长度</span>
public int length(){
if(isEmpty()){
return 0;
}
return rear > front?rear-front:(capacity-(front-rear));
}
<span style="color:#009900;">//向队列中插入元素</span>
public void add(T element){
if(rear == front && elementData[front] != null){
throw new IndexOutOfBoundsException("队列已满");
}
elementData[rear] = element;
rear = (rear+1) > (capacity-1)?0:(++rear);
}
<span style="color:#009900;">//从队列头删除元素</span>
public T delete(){
if(isEmpty()){
throw new IndexOutOfBoundsException("队列为空");
}
T del = (T)elementData[front];
elementData[front] = null;
front = (front+1) > capacity?0:++front;
return del;
}
<span style="color:#009900;">//清空队列</span>
public void clear(){
Arrays.fill(elementData, null);
front = 0;
rear = 0;
}
<span style="color:#009900;">//遍历队列</span>
public void view(){
System.out.print("队列中元素为:");
if(front < rear){
for(int i = front;i < rear;i++){
System.out.print(elementData[i] + " ");
}
}
else{
for(int i = front;i < capacity;i++)
System.out.print(elementData[i] + " ");
for(int i = 0;i < rear;i++)
System.out.print(elementData[i] + " ");
}
}
<span style="color:#009900;">//判断队列是否为空</span>
public boolean isEmpty(){
if(front == rear && elementData[front] == null){
return true;
}
return false;
}
public static void main(String[] args) {
LoopSequenceQueue<String> loopSequenceQueue = new LoopSequenceQueue<>();
loopSequenceQueue.add("hello");
loopSequenceQueue.add("world");
loopSequenceQueue.add("perfect");
loopSequenceQueue.add("3333333");
loopSequenceQueue.delete();
loopSequenceQueue.add("4444444444");
loopSequenceQueue.add("555555555");
loopSequenceQueue.view();
System.out.println("当前队列长度为:" + loopSequenceQueue.length());
}
}
4、队列的链式存储结构
public class LinkedQueue<T> {
private class Node{
private T data;
private Node next;
public Node(){
}
public Node(T element,Node next){
this.data = element;
this.next = next;
}
}
private Node front;
private Node rear;
private int size = 0;
public LinkedQueue(){
this.front = null;
this.rear = null;
}
public LinkedQueue(T element){
rear = new Node(element,null);
front = rear;
size++;
}
<span style="color:#009900;">//获取队列长度</span>
public int length(){
return size;
}
<span style="color:#009900;">//从队尾插入元素</span>
public void add(T element){
Node newNode = new Node(element,null);
if(rear == null){
rear = newNode;
front = rear;
}
else{
rear.next = newNode;
rear = newNode;
}
size++;
}
<span style="color:#009900;">//删除队头元素</span>
public T remove(){
if(size == 0){
throw new IndexOutOfBoundsException("队列为空,不能删除");
}
Node delNode = front;
front = front.next;
delNode.next = null;
size--;
return delNode.data;
}
<span style="color:#009900;">//清空队列</span>
public void clear(){
front = null;
rear = null;
size = 0;
}
<span style="color:#009900;">//遍历队列元素</span>
public void view(){
System.out.print("队列中元素为:");
Node currentNode = front;
while(currentNode != null){
System.out.print(currentNode.data + " ");
currentNode = currentNode.next;
}
System.out.println();
}
public static void main(String[] args) {
LinkedQueue<String> linkedQueue = new LinkedQueue<> ();
linkedQueue.add("hello");
linkedQueue.add("world");
linkedQueue.add("perfect");
linkedQueue.add("3333333");
linkedQueue.remove();
linkedQueue.add("4444444444");
linkedQueue.add("555555555");
linkedQueue.view();
System.out.println("当前队列长度为:" + linkedQueue.length());
}
}
三、二者之间的相互转换
1、用两个栈模拟一个队列
//用栈A和栈B模拟队列Q,A为插入栈,B为弹出栈。
//入队列:入栈A。
//出队列:(1)如果栈B不为空,直接弹出B数据.(2)如果B为空,依次弹出A的数据,放入栈B中,再弹出栈B的数据。
public class StacksToQueue<E>
{
Stack<E> stack1 = new Stack<> ();
Stack<E> stack2 = new Stack<> ();
//向队列尾部添加元素
public void add(E element)
{
stack1.add(element);
}
//从队列头删除元素
public E poll()
{
if(stack2.isEmpty()) //先检查stack2是否为空
{
if(stack1.isEmpty()) //stack2为空时,检查stack1是否为空
{
System.out.println("队列为空,poll操作失败!");
return null;
}
while(!stack1.isEmpty())
stack2.push(stack1.pop());
}
return stack2.pop();
}
public static void main(String[] args)
{
StacksToQueue<Integer> queue = new StacksToQueue<>();
queue.add(2);
queue.add(5);
queue.add(3);
queue.add(8);
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
}
}
2、用两个队列模拟一个栈
//先入栈:所有元素进入queue1.出栈的时候判断栈元素个数是否为1,如果为1,则queue1出队;如果不为1,queue1所有
//元素出队列,入queue2,最后一个元素不入queue2,输出该元素,然后queue2所有元素入queue1.实现了先进后出。
public class QueuesToStack<E>
{
LinkedList<E> queue1 = new LinkedList<> ();
LinkedList<E> queue2 = new LinkedList<> ();
public void push(E element)
{
queue1.add(element);
}
public E pop()
{
if(queue1.size() == 0)
{
System.out.println("栈为空,pop失败!");
return null;
}
while(queue1.size() != 1)
{
queue2.offer(queue1.poll());
}
E element = queue1.poll();
while(!queue2.isEmpty())
queue1.offer(queue2.poll());
return element;
}
public static void main(String[] args)
{
QueuesToStack<Integer> stack = new QueuesToStack<>();
stack.push(5);
stack.push(4);
stack.push(3);
stack.push(2);
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
stack.push(1);
System.out.println(stack.pop());
System.out.println(stack.pop());
}
}
注:本文部分内容参考自《疯狂Java程序员的基本修养》