栈和队列(Java语言版)

一、栈和队列

栈和队列是线性数据结构的典型代表,数组和链表的兄弟姐妹。按照存储方式可分为顺序存储结构和链式存储结构。

1.栈(Stack)

栈只允许在有序的线性资料集合的一端(称为堆栈顶端,top)进行入栈(push)和出栈(pop)的运算,是一种后进先出(Last in First Out)的数据结构,简称 LIFO。

后进先出即最后存入的数据在取出的时候会最先被取出。举个例子,比如厨房叠在一起的碗,先放上去的碗堆在下面,取出的时候最后拿出,后放上去的碗在最上面,取出的时候最先拿出。

堆栈常用一维数组或链表来实现,即顺序存储结构与链式存储结构。

2.队列(Queue)

队列是先进先出(FIFO, First-In-First-Out)的线性表。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。

队列常用一维数组或链表来实现,即顺序存储结构与链式存储结构。

队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加。

二、栈的基本操作(顺序存储结构)

使用数组实现栈

0.初始化栈

由于是使用数组实现的,所以初始化栈时需设置栈的大小。

// 数组栈
public class ArrayStack {	
	int maxSize;
	int[] list;    //数组模拟栈,数据放在该数组
	int top = 0;   //表示栈顶,初始化为0
	// 初始化栈
	public ArrayStack(int maxSize) {
		this.maxSize = maxSize;
		list = new int[maxSize];		
	}
}

1.入栈操作

将要入栈的值存入数组中,同时指针top上移。
如果栈已经满了,则添加失败。
可以在栈满后创建一个更大的数组来优化操作

	// 入栈操作
	public void push(int val) {
		if (top >= maxSize) {
			System.out.println("The stack is max!");
		} else {
			list[top] = val;
			top++;
		}
	}	

2.出栈操作

top指针直接下移即可。

	public void pop() {
		if (top == 0) {
			System.out.println("Error! The stack is empty!");
		} else {
			top--;
		}
	}

3. 打印栈

输出栈中的元素。

	public void display() {
        if(top == 0){
            System.out.println("The stack is empty!");
           return;
        }
		for(int i = 0; i < top; i++) {
			System.out.print(list[i]+" ");
		}
		System.out.println();
	}

4.清空栈

top指针置于起点即可。

    public void clear() {
    	top = 0;
    }

5.判空

    public boolean isEmpty() {
    	if (top == 0) {
    		return true;
    	} else {
    		return false;   		
    	}
    }

6.返回栈顶元素

    public Object peek() {
    	if (top != 0) {
    		return list[top-1];    		
    	} else {
    		return null;
    	}
    }

7.全部整合代码(包括测试)

// 数组栈
public class ArrayStack {
	
	int maxSize;
	int[] list;    //数组模拟栈,数据放在该数组
	int top = 0;   //表示栈顶,初始化为0
	// 初始化栈
	public ArrayStack(int maxSize) {
		this.maxSize = maxSize;
		list = new int[maxSize];
		
	}
	
	// 入栈操作
	public void push(int val) {
		if (top >= maxSize) {
			System.out.println("The stack is max!");
		} else {
			list[top] = val;
			top++;
		}
	}
	
	// 出栈操作
	public void pop() {
		if (top == 0) {
			System.out.println("Error! The stack is empty!");
		} else {
			top--;
		}
	}
	
	// 打印栈
	public void display() {
        if(top == 0){
            System.out.println("The stack is empty!");
           return;
        }
		for(int i = 0; i < top; i++) {
			System.out.print(list[i]+" ");
		}
		System.out.println();
	}
	
	// 清空栈
    public void clear() {
    	top = 0;
    }
    
    // 判空
    public boolean isEmpty() {
    	if (top == 0) {
    		return true;
    	} else {
    		return false;   		
    	}
    }
 
    // 返回栈顶元素
    public Object peek() {
    	if (top != 0) {
    		return list[top-1];    		
    	} else {
    		return null;
    	}
    }
	
	public static void main(String[] args) {
		ArrayStack arrayStack = new ArrayStack(5);

		System.out.println(arrayStack.isEmpty());
		arrayStack.push(1);
		arrayStack.push(2);
		arrayStack.push(3);
		arrayStack.push(4);
		arrayStack.display();		
		arrayStack.pop();
		arrayStack.display();		
		arrayStack.push(5);
		arrayStack.display();
		System.out.println(arrayStack.peek());
		System.out.println(arrayStack.isEmpty());
		arrayStack.clear();
		arrayStack.display();
		System.out.println(arrayStack.peek());
		System.out.println(arrayStack.isEmpty());
	}	
}

三、栈的基本操作(链式存储结构)

使用链表实现栈

0.初始化栈

创建StackNode类,每个StackNode对象表示一个节点。

// 链栈
public class LinkStack{	
	// 链栈的结点构造
	class StackNode{
		int val; // 每个节点存放的值
		StackNode next; // 指向下一个节点
		StackNode() {
		}
		StackNode(int val) { 
			this.val = val; 
		}
		StackNode(int val, StackNode next) {
			this.val = val;
			this.next = next; 
		}		
	}
	int size = 0;
	StackNode topNode;
}

1.入栈操作

即把元素插入栈顶,和头插法相同

	// 入栈操作
	public void push (int val) {
		StackNode newStackNode = new StackNode();
		newStackNode.val = val;
		if (topNode == null) {
			topNode = newStackNode;
			size ++;
		} else {
			newStackNode.next = topNode;
			topNode = newStackNode;
			size ++;
		}
		System.out.println(val + " has been stacked!");
	}

2.出栈操作

top指针直接下移即可。

	public void pop() {
		if (topNode == null) {
			System.out.println("Error! The stack is empty!");
		} else {
			int popValue = topNode.val; // 接收一下出栈的元素,方便后面打印出来
			topNode = topNode.next; // 栈顶指针(即链表头结点)直接指向下一个元素即可删除
			size--;
			System.out.println(popValue + " is out of stack!");
		}
	}

3. 打印栈

输出栈中的元素。

	public void display() {
		StackNode current = topNode;
		while(current != null){
			System.out.print(current.val);
			if (current.next != null) {
				System.out.print(" ");
			}
			current = current.next;
		}
		System.out.println();
	}

4.清空栈

清空topNode。

    public void clear() {
    	if(topNode == null) {
			System.out.println("The stack is empty!");
		} else {
			topNode = null;
			System.out.println("Stack has been emptied!");
		}
    }

5.判空

    public boolean isEmpty() {
		if (topNode == null) {
			return true;
		} else {
			return false;
		}
    }

6.返回栈顶元素

    public int peek() {
		if(topNode == null) {
			System.out.println("The stack is empty!");
		}
		return topNode.val;		
    }

7.全部整合代码(包括测试)

// 链栈
public class LinkStack {	
	// 链栈的结点构造
	class StackNode{
		int val; // 每个节点存放的值
		StackNode next; // 指向下一个节点
		StackNode() {
		}
		StackNode(int val) { 
			this.val = val; 
		}
		StackNode(int val, StackNode next) {
			this.val = val;
			this.next = next; 
		}		
	}
	int size = 0;
	StackNode topNode;
	
	// 入栈操作!即把元素插入栈顶,和头插法相同
	public void push (int val) {
		StackNode newStackNode = new StackNode();
		newStackNode.val = val;
		if (topNode == null) {
			topNode = newStackNode;
			size ++;
		} else {
			newStackNode.next = topNode;
			topNode = newStackNode;
			size ++;
		}
		System.out.println(val + " has been stacked!");
	}
	
	// 出栈操作!
	public void pop () {
		if (topNode == null) {
			System.out.println("Error! The stack is empty!");
		} else {
			int popValue = topNode.val; // 接收一下出栈的元素,方便后面打印出来
			topNode = topNode.next; // 栈顶指针(即链表头结点)直接指向下一个元素即可删除
			size--;
			System.out.println(popValue + " is out of stack!");
		}
	}
	
	public void display () {
		StackNode current = topNode;
		while(current != null){
			System.out.print(current.val);
			if (current.next != null) {
				System.out.print(" ");
			}
			current = current.next;
		}
		System.out.println();
	}
	
	public int peek() {
		if(topNode == null) {
			System.out.println("The stack is empty!");
		}
		return topNode.val;		
	}
	
	public void clear () {
		if(topNode == null) {
			System.out.println("The stack is empty!");
		} else {
			topNode = null;
			System.out.println("Stack has been emptied!");
		}
	}
	
	public boolean isEmpty () {
		if (topNode == null) {
			return true;
		} else {
			return false;
		}
	}
	
	public static void main(String[] args) {
		LinkStack linkStack = new LinkStack();
		
		linkStack.push(2);
		linkStack.push(3);
		linkStack.display();
		
		linkStack.pop();
		
		linkStack.display();
		System.out.println("The topNode is "+linkStack.peek());
		linkStack.clear();
		System.out.println("The stack is null? "+linkStack.isEmpty());
		linkStack.push(8);
		linkStack.push(7);
		linkStack.push(5);
		linkStack.display();
		System.out.println("The stack is null? "+linkStack.isEmpty());
	}
	
}

四、队列的基本操作 (顺序存储结构)

使用数组实现队列

0.初始化队列

public class ArrayQueue {	
	int maxSize; // 队列最大容量
	int[] list; //数组模拟队列,数据放在该数组
	int front = 0; //队头指针front,指向队头元素
	int rear = 0; //队尾指针rear,指向下一个入队元素的存储位置
	int currentSize; // 记录当前队列有几个元素
	// 初始化队列
	public ArrayQueue(int maxSize) {
		this.maxSize = maxSize;
		list = new int[maxSize];
        front = 0;
        rear = 0;
        currentSize = 0;
	}
}

1.入队操作

将要入队的值存入数组中,同时队尾指针rear后移。
如果队列已经满了,则添加失败。
可以在队列满后创建一个更大的数组来优化操作

	// 入队
	public void enQueue (int val) {
		if (currentSize >= maxSize) {
			System.out.println("Error! The queue is full!");
		} else {
			list[rear % maxSize] = val;
			rear ++;
			currentSize ++;
			System.out.println(val + " has been queued!");
		}		
	}

2.出队操作

队头指针front后移

	public void deQueue () {
		if (currentSize == 0) {
			System.out.println("Error! The queue is empty!");
		} else {
			int dequeueValue = list[front];
			front = (front + 1) % maxSize;
			currentSize --;
			System.out.println(dequeueValue + " is dequeued!");
		}
	}

3. 打印队列

输出队列中的元素。

	public void display() {
        if(rear == front){
            System.out.println("The queue is empty!");
           return;
        }
		for(int i = front; i < rear; i++) {
			System.out.print(list[i % maxSize]+" ");
		}
		System.out.println();
	}

4.完整整合代码(包含测试)

package queue;

// 队列
public class ArrayQueue {
	
	int maxSize; // 队列最大容量
	int[] list; //数组模拟队列,数据放在该数组
	int front = 0; //队头指针front,指向队头元素
	int rear = 0; //队尾指针rear,指向下一个入队元素的存储位置
	int currentSize; // 记录当前队列有几个元素
	// 初始化队列
	public ArrayQueue(int maxSize) {
		this.maxSize = maxSize;
		list = new int[maxSize];
        front = 0;
        rear = 0;
        currentSize = 0;
	}
	
	// 入队
	public void enQueue (int val) {
		if (currentSize >= maxSize) {
			System.out.println("Error! The queue is full!");
		} else {
			list[rear % maxSize] = val;
			rear ++;
			currentSize ++;
			System.out.println(val + " has been queued!");
		}		
	}
	
	// 出队
	public void deQueue () {
		if (currentSize == 0) {
			System.out.println("Error! The queue is empty!");
		} else {
			int dequeueValue = list[front];
			front = (front + 1) % maxSize;
			currentSize --;
			System.out.println(dequeueValue + " is dequeued!");
		}
	}
	
	public void display () {
        if(rear == front){
            System.out.println("The queue is empty!");
           return;
        }
		for(int i = front; i < rear; i++) {
			System.out.print(list[i % maxSize]+" ");
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
		ArrayQueue arrayQueue = new ArrayQueue(9);
		
		arrayQueue.enQueue(1);
		arrayQueue.enQueue(2);
		arrayQueue.enQueue(3);
		arrayQueue.enQueue(4);
		arrayQueue.enQueue(5);
		arrayQueue.enQueue(6);
		arrayQueue.enQueue(7);
		arrayQueue.enQueue(8);
		arrayQueue.enQueue(9);
		
		arrayQueue.display();
		
		arrayQueue.deQueue();
		arrayQueue.enQueue(1);
		arrayQueue.display();
	}
}

五、队列的基本操作 (链式存储结构)

使用链表实现队列

0.初始化队列

创建QueueNode对象表示队列节点。声明队头指针和队尾指针。

// 链式队列
public class LinkQueue {
	// 链式队列的结点构造
	static class QueueNode{	
		int val; 
		QueueNode next;
		// 初始化栈
		QueueNode() {
		}
		QueueNode(int val) { 
			this.val = val; 
		}
		QueueNode(int val, QueueNode next) {
			this.val = val;
			this.next = next;
		}
	}
	int size = 0; // 记录当前队列有几个元素
	QueueNode front; // 队头指针front,指向队头元素
	QueueNode rear; // 队尾指针rear,指向下一个入队元素的存储位置
	QueueNode back; // 队尾指针back,指向队尾元素
}

1.入队操作

将要入队的值存入QueueNode 对象中,同时队尾指针后移。

	// 入队
	public void enQueue (int val) {
		 QueueNode queueNode = new QueueNode();
		 queueNode.val = val;
		 if (front == null) {
			 front = queueNode;
			 back = queueNode;
			 System.out.println(val + " has been queued!");
			 size ++;
		 } else {
			 back.next = queueNode;
			 back = back.next;
			 System.out.println(val + " has been queued!");
			 size ++;
		 }	
	}

2.出队操作

队头指针front后移

	public void deQueue () {
		if (front == null) {
			System.out.println("Error! The queue is empty!");
		} else {
			front = front.next;
		}
	}

3. 打印队列

输出队列中的元素。

	public void display () {
		QueueNode current = front;
		while(current != null){
			System.out.print(current.val);
			if (current.next != null) {
				System.out.print(" ");
			}
			current = current.next;
		}
		System.out.println();
	}

4.完整整合代码(包含测试)

package queue;

// 链式队列
public class LinkQueue {
	// 链式队列的结点构造
	static class QueueNode{	
		int val; 
		QueueNode next;
		// 初始化栈
		QueueNode() {
		}
		QueueNode(int val) { 
			this.val = val; 
		}
		QueueNode(int val, QueueNode next) {
			this.val = val;
			this.next = next;
		}
	}

	int size = 0; // 记录当前队列有几个元素
	QueueNode front; // 队头指针front,指向队头元素
	QueueNode rear; // 队尾指针rear,指向下一个入队元素的存储位置
	QueueNode back; // 队尾指针back,指向队尾元素
	
	public void enQueue(int val) {
		 QueueNode queueNode = new QueueNode();
		 queueNode.val = val;
		 if (front == null) {
			 front = queueNode;
			 back = queueNode;
			 System.out.println(val + " has been queued!");
			 size ++;
		 } else {
			 back.next = queueNode;
			 back = back.next;
			 System.out.println(val + " has been queued!");
			 size ++;
		 }
	}
	
	public void deQueue() {
		if (front == null) {
			System.out.println("Error! The queue is empty!");
		} else {
			front = front.next;
		}
	}
	
	public void display () {
		QueueNode current = front;
		while(current != null){
			System.out.print(current.val);
			if (current.next != null) {
				System.out.print(" ");
			}
			current = current.next;
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
		LinkQueue linkQueue = new LinkQueue();		
		linkQueue.enQueue(1);
		linkQueue.enQueue(2);
		linkQueue.enQueue(3);
		linkQueue.enQueue(4);		
		linkQueue.display();
		linkQueue.deQueue();		
		linkQueue.display();		
	}
}

你可能感兴趣的:(数据结构,数据结构,链表,java)