队列和栈的一些算法

栈和队列的基本性质以及操作:

基本性质:
1.栈是先进后出的;
2.队列是先进先出的;
3.栈和队列在实现结构上可以有数组和链表两种形式;
①数组结构实现较容易;
②用链表结构较复杂,因为牵扯很多指针操作。

栈结构的基本操作:
1.pop操作:弹出栈顶元素;
2.top或peek操作:只访问栈顶元素不弹出
3.push操作:从栈顶压入元素;
4.size操作:返回元素个数。

队列结构的基本操作:
1.与栈操作不同的是,push操作:在队头加入元素;
2.pop操作:从队列的尾部弹出一个元素。

栈和队列的基本操作,时间复杂度都是为O(1)的操作;

以下为栈和队列的常用方法:
栈中的常用方法队列的常用方法

深度优先遍历(DFS)和宽度优先遍历(BFS):
1.深度优先遍历可以用栈实现;
2.宽度优先遍历可以用队列实现。

平时使用的递归函数实际上用到了提供的函数系统栈;
递归的过程可以看作递归函数依次进入函数栈的处理过程;
所有用递归函数可以做的过程都一定可以用非递归的方式实现。

例1:

实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作getmin。
要求:
1.pop、push、getmin操作的时间复杂度是O(1);
2.设计的栈类型可以使用现成的栈结构。

解:
方法一:建立两个栈,一个正常栈StackData,另一个放当前最小元素的栈StackMin,只有当前数小于等于StackMin的栈顶时,该数放入StackMin。弹出时,StackData先弹出栈顶元素记为value,然后比较value与StackM栈顶元素哪一个更小,当value=栈顶元素时,StackMin弹出栈顶元素,当value大于栈顶元素时,StackMin不弹出。由此可知,StackMin始终记录着StackData每一步的最小值。
方法二:与方法一相同,建立两个栈,当前数和StackMin栈顶元素比较,较小的压入StackMin,当前数大时,重复压入StackMin的栈顶元素。弹出时,StackMin和StackData同步弹出就可以了,由此可知,StackMin始终记录着StackData每一步的最小值。

1.方法一和方法二都是利用第二个栈StackMin来保存每一步的最小值;
2.实现所有的操作,时间复杂度都为O(1);
3.区别在于方案一稍省空间,略费时间。方案二稍费空间,略省时间。

代码:

	private Stack<Integer> stackdata;
	private Stack<Integer> stackmin;

	public StackMin42() {
		stackdata = new Stack<Integer>();
		stackmin = new Stack<Integer>();
	}

	public void push(int value) {
		stackdata.push(value);
		if (stackmin.empty()) {
			stackmin.push(value);
		}
		if (stackmin.peek() < value) {
			stackmin.push(stackmin.peek());
		}
		if (stackmin.peek() >= value) {
			stackmin.push(value);
		}
	}

	public void pop() {
		stackmin.pop();
		stackdata.pop();

	}

	public int peek() {
		return stackmin.peek();
	}

	public int getmin() {
		 return stackmin.peek();
	 }

例2:

编写一个类,只能用两个栈结构实现队列,支持队列的基本操作(add,poll,peek)。

解:
一个栈(StackPush)完全压入数据,然后依次出栈切压入第二个栈(StackPop),就可以实现先进先出的队列结构;
注意两个点:
1.如果StackPush要往StackPop中倒入数据,那么必须要把StackPush中的所有数据一次性倒完;
2.如果StackPop中有数据,则不能发生倒数据的行为。
代码:

	public Stack<Integer> stackPush;
	public Stack<Integer> stackPop;

	public TwoStacksQueue44() {
		stackPush = new Stack<Integer>();
		stackPop = new Stack<Integer>();
	}

	// 元素进栈
	public void add(int pushInt) {
		stackPush.push(pushInt);
	}

	public int poll() {
		if (stackPop.empty() && stackPush.empty()) {
			throw new RuntimeException("Queue is empty!");
		} else if (stackPop.empty()) {
			while (!stackPush.empty()) {
				stackPop.push(stackPush.pop());
			}
		}
		return stackPop.pop();
	}

例3:

实现一个栈的逆序,但是只能用递归函数和这个栈本身的操作实现,而不能自己申请额外的数据结构。

解:
代码1:移除栈底元素并返回;

public int get(Satck<Integer> stack) {
	int result = stack.pop();
	if(stack.isEmpty()) {
		return result;
	} else {
			int last = get(stack);
			stack.push(result);
			return last;
	}
}

**代码2:**逆序主方法。

public void rexerse(Stack<Integer> satck) {
	if(stack.isEmpty()) {
		return;
	}
	int i = get(stack);
	reverse(stack);
	stack.push(i);
}

例4:

一个栈(stack)中元素类型为整型,现在想将该栈从顶到底按从小到大排序,只许申请一个栈,除此之外可以申请新的变量,但不能申请额外的数据结构。如何完成排序?

解:
申请一个叫help的栈,然后从stack中弹出栈顶元素进入help,当弹出的元素(a)大于help栈顶元素时,help中的元素依次弹出并放入stack中,然后将a压入help,然后将之前help中的元素依次从stack中弹出并压入help中,最后将help的元素从新压入stack中就完成排序了。

代码:

	private Stack<Integer> stackpush;
	private Stack<Integer> stackpop;

	public StackSort46() {
		stackpush = new Stack<Integer>();
		stackpop = new Stack<Integer>();
	}

	public void sort() {
		while (!stackpush.empty()) {
			stackpop.push(stackpush.pop());
		}

		while (!stackpop.empty()) {
			int value = stackpop.pop();
			if (stackpush.empty()) {
				stackpush.push(value);
			} else {
				while (!stackpush.empty() && stackpush.peek() > value) {
					stackpop.push(stackpush.pop());
				}
				stackpush.push(value);
			}
		}
	}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值