目录
前言:
栈实现的是一种后进先出(last-in,first-out,LIFO)策略,在进制转换中将十进制数转换为n进制便是"除n取余,逆序排列",其中我们又看到了经典的逆序,这当然是栈最擅长的,而要转换的数若非十进制则先将其转换为十进制再进行前面的操作。
提示:以下是本篇文章正文内容, 全是干货
一、进制相关概念及转换方法
1.相关概念
数制:也称为计数制,是一种计数的方法,是用一组固定的符号和统一的规则来表示数值的方法。在计数过程中采用进位的方法称为进位计数制(进制),包括数位、基数和位权三个要素。
-
数位:指数字符号在一个数中所处的位置。
-
基数:指在某种进位计数制中数位上所能使用的数字符号的个数。例如十进制的基数为10。
-
位权:数制中某一位上的1所表示数值的大小(所处位置的价值)。例如十进制的230,1的位权是100,2的位权是10,3的位权是1。
2.输入非十进制数
若输入的为非十进制数则先将其转为十进制数,具体做法为:将每位对应的数字乘以位权再求和,下面分别以二进制数及八进制数为例:
二进制:1101 -> 1*2^3+1*2^2+0+1=13
八进制:0241 -> 2*8^2+4*8^1+1=161
3.转为任意进制
方法:"除n取余,逆序排列"
1.除以基数记录商和余数,如果商为0,则转换结束。
2.重复步骤,将商再次除以16,记录新的商和余数。
3.倒序排列余数,将所有步骤中得到的余数倒序排列。
4.处理特殊余数。如果余数是10到15,则在十六进制中用字母A到F表示。
其中倒着写部分可以由栈来实现。具体操作便是将余数逐个放入栈中,然后依次出栈便完成操作,下面以将十进制数7692转换为十六进制数为例:
(1)7692除以16,商480,余数12(在十六进制中表示为C)。
(2)480除以16,商30,余数0(在十六进制中表示为30)。
(3)30除以16,商1,余数14(在十六进制中表示为E)。
(4)1除以16,商0,余数1(在十六进制中表示为1)。
(5)因此,7692的十六进制表示为1EOC。
二、代码实现
1.创建结点
关于结点的建立就不赘述了,这里要注意的是后面要用到的类模板Stack要先提前声明,否则在Node类里声明友元时会报错。
template<class T>class Stack; //向前声明
template<class T>
class Node {
private:
T m_data; //数据域
Node* m_next; //指针域
public:
Node(const T& val) {
this->m_data = val;
} //有参构造
Node& operator=(const Node& rhs) = delete; //禁止赋值
friend class Stack<T>; //声明友元
};
2.创建栈
入栈出栈清空都是基本的写法,不多赘述。
template<class T>
class Stack {
private:
Node<T>* m_top = nullptr; //栈顶指针
public:
Stack() = default; //默认构造
Stack(const Stack&) = delete; //禁止复制
Stack& operator=(const Stack&) = delete; //禁止赋值
~Stack() {
clear();
}; //析构
void clear(); //清空栈
void push(const T& val); //入栈
void pop();//出栈
bool emp