本文主要是数组和链表实现栈、链表实现队列。栈和队列的结构都比较简单,用链表实现时都是单链表实现的!
一、栈
先进后出。先进来的元素保存在栈的最底部,新来的元素则在栈顶堆积,直到栈满为止;而取元素的时候,只能从栈顶取,直到栈空为止。栈有两种方法:压栈(push)和弹栈(pop)。
数组最好只实现固定栈(栈的容量数量固定),链表可以实现动态栈(因为进出栈时,永远只需要对链表的头操作)。
1.1、数组实现栈
package com.review07;
public class MyArrayStack {
//存数据的数组
private int [] data;
//栈的最大长度
private int size;
//栈顶的位置
private int top;
//构造方法初始化栈
public MyArrayStack(int size) {
this.data = new int[size];
this.size = size;
this.top = -1;
}
//获取栈的长度
public int getSize() {
return size;
}
//获取栈顶
public int getTop() {
return top;
}
//判断是否为空栈,(空:true)
public boolean isEmpty() {
return top == -1;
}
//判断是否为满栈
public boolean isFull() {
return (top+1) == size;
}
//压栈操作
public void push(int data) {
if(isFull()) {
try {
throw new Exception("栈已满!");
} catch (Exception e) {
e.printStackTrace();
}
}else {
top ++;
this.data[top] = data;
}
}
//弹栈操作
public int pop() throws Exception {
if(isEmpty()) {
System.out.println("栈是空的,无元素可以弹出!");
throw new Exception("栈是空的,无元素可以弹出!");
}else {
top --;
return this.data[top]; //返回新的栈顶元素
}
}
//获取栈顶元素,但不弹栈
public int getTopValue() {
return this.data[getTop()];
}
//main方法测试
public static void main(String[] args) {
MyArrayStack myArrayStack = new MyArrayStack(10);
myArrayStack.push(23);
myArrayStack.push(4);
myArrayStack.push(2);
myArrayStack.push(5);
myArrayStack.push(7);
System.out.println("现在栈顶元素为:"+ myArrayStack.getTopValue());
while(!myArrayStack.isEmpty()) {
try {
System.out.println(myArrayStack.getTopValue()+
"弹出栈顶元素后,新的栈顶元素是:"+myArrayStack.pop());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
1.2、链表实现栈
package com.review07.linkedStack;
/**
* 用链表实现栈
*/
public class MyLinkedStack {
private Node header; //栈顶元素
private int elementCount;//栈内元素个数
private int size;//栈的大小
/**
* 构造函数,构造出一个空的栈
*/
public MyLinkedStack() {
this.header = null;
this.elementCount = 0;
this.size = 0;
}
/**
* 通过构造函数,构造出一个自定义大小的栈
*/
public MyLinkedStack(int size) {
this.header = null;
this.elementCount = 0;
this.size = size;
}
//设置头结点
public void setHeader(Node header) {
this.header = header;
}
//判断栈是否已满
public boolean isFull() {
if(elementCount ==size) {
return true;
}
return false;
}
//判断栈是否为空的
public boolean isEmpty() {
if(elementCount == 0) {
return true;
}
return false;
}
//压栈
public void push(Object value) {
if(this.isFull()) {
throw new RuntimeException("栈满了!");
}
//这里将原来的header作为参数传入,然后以新new出来的Node作为header
header = new Node(value,header);
elementCount ++;
}
//弹栈
public Object pop() {
if(this.isEmpty()) {
throw new RuntimeException("栈空了,无法弹出元素");
}
Object obj = header.getElement();
header = header.next;
elementCount --;
return obj;
}
//返回栈顶元素
public Object getHeaderElement() {
if (this.isEmpty()) {
throw new RuntimeException("栈是空的");
}
return header.getElement();
}
//main方法测试
public static void main(String[] args) {
MyLinkedStack myArrayStack = new MyLinkedStack(10);
myArrayStack.push(23);
myArrayStack.push(4);
myArrayStack.push(2);
myArrayStack.push(5);
myArrayStack.push(7);
System.out.println("现在栈顶元素为:"+ myArrayStack.getHeaderElement());
while(!myArrayStack.isEmpty()) {
try {
System.out.println(myArrayStack.getHeaderElement()+"弹出栈顶元素后,新的栈顶元素是:"+myArrayStack.pop());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
二、队列
先进先出
队列每一次都是要先删除前面的元素,数组越是删除前面的元素效率越是低,所以这里就不再研究数组实现队列了。相反的是使用链表实现会更简单,效率会更高!另外队列的结构比较简单,只需要用单链表就够了,进队列时,需要记录队尾。
下面用链表实现队列:rear记录尾,front记录头
package com.review07.linkedQueue;
/**
* 单链表实现的队列
*/
public class MyLinkedQueue {
Node front;//队首指针
Node rear; //队尾指针
public MyLinkedQueue() {
this.front = null;
this.rear = null;
}
/**
* 将一个对象追加到队列的尾部
*/
public void enqueue(Object obj) {
//如果队列是空的
if(rear == null && front == null) {
rear = new Node(obj);
front = rear;
} else {
Node node = new Node(obj);
rear.next = node;
rear = rear.next;
}
}
/**
* 队首对象出队
* @return 出队的对象,队列空时返回null
*/
public Object dequeue() {
//如果队列空
if(front == null) {
return null;
}
else if(front == rear && rear != null) { //队列里只有一个元素
Node node = front;
rear = null;
front = null;
return node.element;
}
Object obj = front.element;
front = front.next;
return obj;
}
//main测试
public static void main(String[] args) {
MyLinkedQueue myLinkedQueue = new MyLinkedQueue();
myLinkedQueue.enqueue("张三");
myLinkedQueue.enqueue("Tom");
myLinkedQueue.enqueue("Jack");
myLinkedQueue.enqueue("小米");
while(myLinkedQueue.front != null) {
System.out.println(myLinkedQueue.dequeue());
}
}
}