【数据结构】栈与队列



栈和队列

栈和队列的数据操作范围仅限于逻辑上特定的某端,栈先进后出,队列先进先出。


一、栈

1.栈的ADT接口

操作接口功能返回类型
size()报告栈的规模int
empty()判断栈是否为空bool
push(e)将e插至栈顶void
pop()删除栈顶对象T
top()引用栈顶对象T&

2.Stack模板类

#include "../Vector/Vector.h" //以向量为基类,公有派生出栈模板类
template <typename T> class Stack:public Vector<T>
{
public://size()、empty()及其他的开放接口,可以直接沿用
    void push (T const& e){  //入栈:相当于将新元素作为向量的末元素插入
    	insert(size(),e);
    }
    T pop(){  //出栈:等效于删除向量的末元素
    	return remove(size()-1);
    }
    T& top(){  //取顶:直接返回向量的末元素
    	return (*this)[size()-1];
    }
};

3.进制转换问题

进制转换的原理:将一个10进制的数X转换成n位h进制的数:

X = ( b n − 1 b n − 2 … b 2 b 1 b 0 ) h X = b n − 1 ∗ h n − 1 + b n − 2 ∗ h n − 2 + … + b 2 ∗ h 2 + b 1 ∗ h 1 + b 0 ∗ h 0 X 0 = X ÷ h = b n − 1 ∗ h n − 2 + b n − 2 ∗ h n − 3 + … + b 2 ∗ h 1 + b 1 ∗ h 0 ⋯ ⋯ b 0 X 1 = X 0 ÷ h = b n − 1 ∗ h n − 3 + b n − 2 ∗ h n − 4 + … + b 2 ∗ h 0 ⋯ ⋯ b 1 ⋮ X n − 1 = X n − 2 ÷ h = 0 ⋯ ⋯ b n − 1 \begin{array}{l} X = {\left( {{b_{n - 1}}{b_{n - 2}} \ldots {b_2}{b_1}{b_0}} \right)_h}\\ X = {b_{n - 1}}*{h^{n - 1}} + {b_{n - 2}}*{h^{n - 2}} + \ldots + {b_2}*{h^2} + {b_1}*{h^1} + {b_0}*{h^0}\\ {X_0} = X \div h = {b_{n - 1}}*{h^{n - 2}} + {b_{n - 2}}*{h^{n - 3}} + \ldots + {b_2}*{h^1} + {b_1}*{h^0} \cdots \cdots {b_0}\\ {X_1} = {X_0} \div h = {b_{n - 1}}*{h^{n - 3}} + {b_{n - 2}}*{h^{n - 4}} + \ldots + {b_2}*{h^0} \cdots \cdots {b_1}\\ \vdots \\ {X_{n - 1}} = {X_{n - 2}} \div h = 0 \cdots \cdots {b_{n - 1}} \end{array} X=(bn1bn2b2b1b0)hX=bn1hn1+bn2hn2++b2h2+b1h1+b0h0X0=X÷h=bn1hn2+bn2hn3++b2h1+b1h0b0X1=X0÷h=bn1hn3+bn2hn4++b2h0b1Xn1=Xn2÷h=0bn1

对十进制数X,不断除h取余,将余数(低位到高位)压入栈中,直到商为0,再依次将高位到低位从栈中取出。

迭代实现代码:

void convert(stack<char>& S, __int64 n, int base){//十进制数n到base进制数的转换
	static char digit[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	while(n!=0){
		int remainder = (int)(n%base);
		S.push(digit[remainder]);
		n/=base;
	}
}//新进制下由高到低的各数位,自顶向下保存在栈中

二、队列

队列中约定,新对象只能由队尾插入其中,只能从对头一端删除已有的元素。

1.队列中的ADT接口

操作接口功能返回类型
size()报告队列的规模(元素总数)int
empty()判断队列是否为空bool
enqueue(e)将e插入队尾void
dequeue()删除队首对象T
front()引用队首对象T&

2.Queue模板类

代码如下(示例):

#include "../List/List.h" //以List为基类,公有派生出栈模板类
template <typename T> class Stack:public List<T>
{
public://size()、empty()及其他的开放接口,可以直接沿用
    void enqueue (T const& e){  //入队:尾部插入
    	insertAsLast(e);
    }
    T dequeue(){  //出队:首部删除
    	return remove(first());
    }
    T& front(){  //队首
    	return first()->data;
    }
};

3.用栈来实现队列

用两个栈来实现队列的入队和出队,原理如下:
①将Stack1作为要使用的队,判断Stack2是否为空,若不为空,则先将Stack2元素压入Stack1中,再将入队元素压入(pop)进Stack1中,自然地,入队元素位于Stack1栈的栈顶。
②出队时,若Stack2为空,则将Stack1中的元素一一弹出并压入Stack2中,直到Stack1中元素为空,这时候Stack2的栈顶对象就是队列的队首对象。如果Stack2不为空时,则直接弹出Stack2的栈顶对象

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }
 
    int pop() {
        assert((!stack1.empty())||(!stack2.empty()));//确保两个栈中至少有一个有元素
        if(stack2.empty())
            while(!stack1.empty())
            {
                int tmp = stack1.top();
                stack2.push(tmp);
                stack1.pop();
            }
        int ret = stack2.top();
        stack2.pop();
        return ret;
    }
private:
    stack<int> stack1;
    stack<int> stack2;
};

总结

栈和队列都含有一个能够删除集合中的特定元素的方法。

参考文献

[1]: https://www.zhihu.com/question/20993504.
[2]:https://cloud.tencent.com/developer/article/1643318.
[3]:邓俊辉.数据结构(C++语言版).北京:清华大学出版社,2010年8月第一版,ISBN:978-7-302-33064-6.

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值