加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

【数据结构】堆栈和队列

发布时间:2020-12-15 06:00:38 所属栏目:安全 来源:网络整理
导读:堆栈又叫栈(堆栈和堆是两种不同的数据结构),和队列是两种极为常见的数据结构。这两种数据结构多少有点相对立的意思,一个是先进后出,一个是先进先出。概念上虽然很简单,很好理解,但其实其中有非常大的学问。在高并发系统的请求处理,操作系统消息机制

堆栈又叫栈(堆栈和堆是两种不同的数据结构),和队列是两种极为常见的数据结构。这两种数据结构多少有点相对立的意思,一个是先进后出,一个是先进先出。概念上虽然很简单,很好理解,但其实其中有非常大的学问。在高并发系统的请求处理,操作系统消息机制中这两种数据结构有极大的应用,是两种应用很广的数据结构。

堆栈:



队列:


堆栈

堆栈的有进栈和出栈两种基本操作。进栈过程是数据由栈顶推入栈,由栈底开始逐一放置直到数据装满整个栈。出栈过程是数据由处于最上层的数据推出栈,直到栈底数据被推出,后进栈的数据在出栈过程中优先。堆栈的实现可以基于数组,链表等形式。堆栈对象中一般保存有栈顶对象引用,栈的深度和进栈出栈成员函数。如下给出一个基本堆栈的JAVA代码,基于数组的实现。

public class Stack {
	private int capacity = 10;
	private int[] stackArray = new int[capacity];
	private int top;
	
	public boolean push(int value){
		if(top == stackArray.length) return false;
		stackArray[top++] = value;
		return true;
	}
	
	public int pop() throws NoSuchElementException{
		if(top == 0) throw new NoSuchElementException();
		return stackArray[--top];
	}
	
	public int getTop() throws NoSuchElementException{
		if(top == 0) throw new NoSuchElementException();
		return stackArray[top - 1];
	}
}
在java.util容器库中提供的Stack是基于Vector容器实现的队列,所以其容量上限为内存上限,所以存储容量很大。

队列

其实队列的概念也很简单,所谓先进先出。数据从尾部进入,从头部推出。队列对象中一般保存有头部引用和尾部两个引用。这里给出一个基于数组实现的队列JAVA代码

public class Queue {
	int capacity = 10;
	int[] queueArray = new int[capacity];
	int top = 0;
	
	public boolean push(int value){
		if(top == queueArray.length) return false;
		queueArray[top++] = value;
		return true;
	}
	
	public int pop() throws NoSuchElementException{
		if(top == 0) throw new NoSuchElementException();
		int value = queueArray[0];
		int i = 0; 
		int j = i + 1;
		while(j < top){
			queueArray[i] = queueArray[j];
			i++;
			j++;
		}
		top--;
		return value;
	}
	
	public int getFirst() throws NoSuchElementException{
		if(top == 0) throw new NoSuchElementException();
		return queueArray[0];
	}
	
	public int getLast() throws NoSuchElementException{
		if(top == 0) throw new NoSuchElementException();
		return queueArray[top - 1];
	}
}


队列常常也有首尾相连的情况,称为循环队列(如下图)。


循环队列需要注意头指针和位置的操作,明确当前尾指针是否越界等。这里给出一个循环队列的实现。

class QueueNode{
	int value;
	QueueNode previous;
	QueueNode next;
	
	public QueueNode(QueueNode pre){
		this.previous = pre;
	}
}

public class CircleQueue {
	int capacity = 10;
	QueueNode head = null;
	QueueNode tail = null;
	
	public CircleQueue(){
		QueueNode cur = tail = head = new QueueNode(null);
		for(int i = 0; i < capacity; i++){
			cur.next = new QueueNode(cur);
			cur = cur.next;
		}
		cur.next = head;
		head.previous = cur;
	}
	
	public void push(int value){
		if(tail.next == head) throw new IndexOutOfBoundsException();
		tail.next.value = value;
		tail = tail.next;
	}
	
	public int pop() throws NoSuchElementException{
		if(tail == head) throw new NoSuchElementException();
		int value = tail.value;
		tail = tail.previous;
		return value;
	}
}

建议大家可以看一下java.util.Stack和java.util.Queue的源代码,可以帮助了解这两种数据结构的实现和使用。参考博文《【源代码】java.util.Stack & Queue》


面试常见问题

1.堆栈和队列的异同

相同点:首先堆栈和队列都可以使用链表或者数组实现。

不同点:首先是对象进出操作的不同,堆栈是先进后出,队列是先进先出。


2.涉及一种堆栈包含一个获取最大值的成员方法getMaximum(),要求时间复杂度为O(1)。

这里只需要在堆栈对象中加入另外一个栈stack_max,用来记录当前最大数值。假设新入栈元素n的值大于stack_max[n-1]的最大值,则stack_max[n] = n,否则stack_max[n] =stack_max[n - 1]。出栈时将stack_max的栈顶元素同时推出即可。这里提供改进后的JAVA代码:


这里还有另外一个升级版问题,如果把堆栈改成队列,如何设计一个getmaximum(),让操作的时间复杂度越小越好。


3.使用堆栈来实现一个队列。

首先明确差异,堆栈是先进后出,需要用它来实现一个先进先出的结构,可以考虑使用两个堆栈。此时入栈操作与之前相同,只是出栈操作需要对原堆栈推入另一个堆栈,这样栈底对象就成为了栈顶对象,然后做一个出栈操作就可以推出栈顶对象,最后将剩下的对象再推回原堆栈即可(如下图)。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读