`

堆栈变体以及栈和队列的相互实现

阅读更多
前面讲到了如何用数组以及链表实现一个基本的堆栈和队列,这篇文章介绍如何实现一个可以在O(1)时间复杂度下得到最小元素的堆栈,以及用堆栈实现一个队列,用队列实现一个堆栈。

1,实现一个可以得到最小元素的堆栈, 要求pop(),push(),getMin()的时间复杂度都为O(1).

如果我们按照普通的思路,类中有两个成员变量,value和minValue,当pop一个元素后,我们就需要更新minValue, 从而要遍历堆栈里剩余的元素,时间复杂度为O(n),假设堆栈中有n个元素,因此这个方法不符合题意。

我们想到用每个元素都记录当前的最小元素,当push一个新的元素进来,这个新的元素连同最小元素都被记录在堆栈中,我们先不考虑pop,实现代码如下:
public class StackWithMin extends Stack<EleWithMin>{
	public void push(int val) {
		int min = Math.min(val, min());
		super.push(new EleWithMin(val, min));
	}

	public int pop() {
		/* 
		after we pop a element,
		how can we update the min in
		stack if this is the minimum value
		*/
		super.pop().value;

	}
	public int min(){
		if(this.isEmpty()){
			return Integer.MAX_VALUE;
		} else {
			return peek().min;
		}
	}
}

class EleWithMin {
	public int value;
	public int min;

	public EleWithMin(int value, int min) {
		this.value = value;
		this.min = min;
	}
}


他的确可以在O(1)的时间内得到最小元素,但是pop后,我们仍然需要更新最小值,时间复杂度大于O(n)。并且浪费空间,因为每个元素都要记录一个当前的最小元素。我们换另一种方法,用另外一个堆栈来记录最小元素。代码如下:
import java.util.Stack;

public class StackWithMin extends Stack<Integer> {
	Stack<Integer> minStack;

	public StackWithMin() {
		minStack = new Stack<Integer>();
	}
	public void push(int val) {
		super.push(val);
		if(minStack.isEmpty() || minStack.peek() >= getMin()){
			minStack.push(val);
		}
	}

	public Integer pop(){
		int value = super.pop();
		if(value == getMin()){
			minStack.pop();
		}
		return value;
	}

	public int getMin() {
		if(minStack.isEmpty()) {
			return Integer.MAX_VALUE;
		} else {
			return minStack.peek();
		}
	}
}


2,用队列实现一个堆栈

借用两个队列,实现堆栈后进先出的原理。代码如下:
import java.util.LinkedList;
import java.util.Queue;

public class MyStack {
	Queue<Integer> q1 = new LinkedList<Integer>();
	Queue<Integer> q2 = new LinkedList<Integer>();
	
	public void push(int val) {
		q1.offer(val);
	}
	
	public int pop() {
		while(q1.size() > 1) q2.offer(q1.poll());
		int result = q1.poll();
		Queue<Integer> q = q1;
		q1 = q2;
		q2 = q1;
		return result;
	}
	
	public int peek() {
		while(q1.size() > 1) q2.offer(q1.poll());
		int result = q1.poll();
		q2.offer(result);
		Queue<Integer> q = q1;
		q1 = q2;
		q2 = q;
		return result;
	}
	
	public boolean isEmpty() {
		if(q1.size() == 0) {
			return true;
		} else {
			return false;
		}
	}

}


3,用堆栈实现队列
思路和上一题类似,这里用两个堆栈来实现队列先进先出的原理。代码如下:
import java.util.Stack;

public class MyQueue {
	Stack<Integer> stack1 = new Stack<Integer>();
	Stack<Integer> stack2 = new Stack<Integer>();
	
	public void offer(int val) {
		stack1.push(val);
	}
	
	public int element() {
		while(!stack1.isEmpty())
			stack2.push(stack1.pop());
		int result = stack2.pop(); //删除第一个元素
		while(!stack2.isEmpty())
			stack1.push(stack2.pop());
		return result;
	}
	
	public int peek() {
		while(!stack1.isEmpty())
			stack2.push(stack1.pop());
		int result = stack2.peek(); //不删除第一个的元素
		while(!stack2.isEmpty())
			stack1.push(stack2.pop());
		return result;
	}
	
	public boolean empty() {
		if(stack1.isEmpty())
			return true;
		return false;
	}
}
分享到:
评论

相关推荐

    热-数据结构中的栈和队列:理解、应用与比较

    除了基本的栈和队列,还有一些变体,如带优先级的堆栈(Priority Stack)和循环队列(Circular Queue)。优先级栈允许根据元素的优先级决定何时弹出,常用于事件驱动系统;循环队列则解决了普通队列在满或空时的边界...

    软件基础_2018_12+第五章数据结构+栈_队列1

    数据结构是计算机科学中的核心概念,它涉及到如何高效地组织和管理数据,以便于执行各种计算和操作。在本章中,我们将深入探讨其中的两...熟练掌握这些基本数据结构的原理和实现方式,对于提升编程能力有着重要的作用。

    计算机数据结构堆栈与队列

    总结来说,堆栈和队列作为基本数据结构,在计算机科学和软件开发中有着广泛的应用,它们的实现和操作对理解算法和程序设计至关重要。通过学习和熟练掌握这些概念,可以有效地提高编程效率和代码质量。

    数据结构图,堆栈,队列,最小生成树

    另外,还有循环队列和双端队列等变体,分别提供更好的性能和灵活性。 “最小生成树”是图论中的一个经典问题,用于找到连接所有顶点的边的权重总和最小的子集,这在网络设计、成本计算等领域有广泛应用。Prim算法和...

    数据结构各章自测题及答案

    栈和队列的变体,如堆栈和双端队列,也具有重要应用。 ### 第4—5章 串和数组 字符串是特殊的线性表,通常用于处理文本数据。数组则是固定大小的一维或多维数据集合,提供连续存储和快速访问,适合处理矩阵等结构。...

    队列的数据结构的学习 自我心得

    队列是一种基础且重要的数据...学习队列数据结构不仅可以帮助你理解和解决实际问题,也是进一步学习更复杂数据结构如堆栈、树、图等的基础。通过不断实践和应用,你将能够更好地掌握队列的精髓,提升自己的编程能力。

    数据结构演示.FLASH

    堆栈和队列的变体,如双端队列(deque)和优先级队列,提供了更灵活的操作选项。 动画演示通常会通过生动的例子展示这些数据结构的插入、删除、查找等操作过程,以及它们在实际问题中的应用。例如,它可能会通过...

    东北大学数据结构实验四完整代码

    实验可能包括栈和队列的实现,以及它们在实际问题中的应用。 4. **树结构**:二叉树是最常见的树形数据结构,包括二叉搜索树、完全二叉树、满二叉树和平衡二叉树。实验中可能需要实现基本的树操作,如查找、插入和...

    关于数据结构的资料

    6. **堆栈和队列的变体**:如双端队列(deque)允许在两端进行插入和删除,栈和队列的组合(如队列堆栈)提供灵活的操作。 数据结构的重要性在于它直接影响到算法的效率。选择合适的数据结构可以显著提升算法性能,...

    数据结构笔记

    9. **堆栈、队列和双端队列的变体**:除了基本的栈和队列,还有多种变体,如循环队列、堆栈队列(又称双端队列)等,它们提供了更灵活的操作。 《数据结构笔记》的作者可能会详细讨论这些数据结构的实现、特性以及...

    c语言版数据结构书内44种结构实现.rar

    堆栈和队列的变体,如双端队列(deque)和堆栈,也十分重要。deque允许在两端进行插入和删除操作,而堆栈允许在顶部进行操作的同时保持其LIFO属性。 图论中的数据结构,如最小生成树(Prim算法或Kruskal算法)、...

    数据结构试验.7z数据结构试验.7z

    还有堆栈和队列的变体,如双端队列(deque)和优先级队列(Priority Queue),它们在算法设计中也有广泛应用。 在进行数据结构试验时,可能会涉及以下几个方面: 1. 实现基本数据结构:如编写链表、栈、队列、树和...

    山东大学数据结构部分笔记.rar

    6. **特殊数据结构**:如哈希表、堆栈、队列的变体(如双端队列)、图的最小生成树(如Prim算法和Kruskal算法)等。 7. **动态规划和贪心策略**:在解决一些优化问题时,数据结构与动态规划和贪心策略相结合,能...

    数据结构与算法(java语言版)

    包括栈和队列的顺序存储和链式存储实现,以及它们在进制转换、括号匹配检测和迷宫求解中的应用。本章通过实际的例子展示了这些基本数据结构的强大应用。 第五章“递归”着重讲述了递归的概念、与堆栈的关系,以及...

    数据结构课程

    堆栈和队列的变体,如双端队列和优先队列,进一步扩展了其功能。 散列表(哈希表)是一种通过哈希函数将键映射到数组索引的数据结构,提供了快速的查找、插入和删除操作。它的平均时间复杂度可以达到O(1),但在最坏...

    严蔚敏数据结构习题集答案

    6. **其他高级数据结构**:例如堆栈、队列的变体,如双端队列、优先队列;集合和映射结构,如字典和关联数组;图的搜索算法,如拓扑排序和最小生成树算法(Prim或Kruskal)。 严蔚敏数据结构习题集中的答案提供了对...

    c++数据结构习题级答案

    7. **堆栈和队列的变体**:如双端队列(deque)提供了在两端插入和删除的能力,循环队列解决了队列满或空的问题。 8. **动态数组**:如C++中的`std::vector`,在内存不足时自动扩展,同时提供了数组的功能。 在...

    一个很好的数据结构课件

    接下来是高级数据结构,如堆、队列和优先队列、堆栈、队列的变体(如双端队列)、图的遍历算法(如深度优先搜索和广度优先搜索)。这些数据结构在解决实际问题中有着广泛的应用,如任务调度、网络路由等。 此外,...

    数据结构相关章节习题

    第九章和第十章可能涉及到高级数据结构,如堆、栈、队列的变体(如堆栈、堆队列),以及特殊用途的数据结构,如二叉索引树(B树)、红黑树等。这部分习题可能会设计复杂的数据结构操作,要求你理解它们的平衡性质和...

    数据结构习题

    读者还会接触到一些高级数据结构,如堆栈、队列的变体(如堆栈队列、循环队列),树的遍历(前序、中序、后序),树的平衡(如AVL树、红黑树),图的遍历和最短路径算法(如Dijkstra算法、Floyd算法),以及动态规划...

Global site tag (gtag.js) - Google Analytics