栈(Stack)是一种特殊的线性表,是一种操作受限的线性表,所有的插入和删除操作都限定在表尾进行的,是一种后进先出的线性表。
假设栈S = (A1,A2,......,An),从A1开始入栈直到An结束,则称A1为栈底元素,An为栈顶元素。要是出栈的话又会从最后进栈的An开始,所以可以看出这种结构是后进先出的(简称LIFO结构),如下图所示:
![8b2b66188c582b49418c3d399da8b4e6.png](https://img-blog.csdnimg.cn/img_convert/8b2b66188c582b49418c3d399da8b4e6.png)
1.栈的表示和实现
和线性表类似,栈也有两种存储表示方式:顺序栈和链式栈。
1.1 顺序栈
定义:
#define MAXSIZE 100
1.2 链式栈
![2e306721367a661b4761035f182d9f90.png](https://img-blog.csdnimg.cn/img_convert/2e306721367a661b4761035f182d9f90.png)
定义:
typedef struct
{
DataType Data; /* 数据域 */
struct node *next; /* 指针域 */
}node,*linklist;
2.栈的基本算法
(1)进栈:
- 判断栈是否满了
- 栈顶指针 + 1:S -> top ++;
- x入栈:S -> Elem[S -> top] = x;
(2)出栈:
- 判断栈是否为空
- 栈顶指针 - 1,出栈
(3)栈的遍历:
void StackTraverse(sqstack *S)
{
while((S -> top) > -1)
{
x = S -> Elem[S -> top];
S -> top --;
printf(x);
}
}
2.2 链式栈的基本算法
2.2.1 进栈:
算法思想:
(1)动态分配存储空间
p = (linklist)malloc(sizeof(node));
(2)给数据成员赋值
p -> Data = x;
(3)给指针成员赋值
p -> next = top;
(4)修改栈顶指针
top = p;
代码实现:
void StackPush(linklist top)
{
linklist p;
p = (linklist)malloc(sizaof(node));
p -> Data = x;
p -> next = top;
top = p;
}
2.2.2 出栈:
算法思想:
(1)判断栈是否为空
if(top == NULL)
(2)将p指向栈顶
p = top;
(3)栈顶指针下移
top = top -> next;
(4)释放存储空间
free(p);
代码实现:
void StackPop(linklist top)
{
linklist p;
if(top == NULL)
{
printf("Stack is empty.");
}
else
{
p = top;
top = top -> next;
free(p);
}
}
3.栈的应用——数制转换
十进制数转换成其他d进制数,是计算机实现计算的基本问题,在学校C语言课程中我们学过十进制数转换二进制数有一个口诀,叫做“除2取余,倒计数”,向其他进制转换也是一样的过程,把其总结为一个公式如下:
N = (N / d) * d + N % d
例如:十进制数1348转换为八进制数为2504,转换过程如下:
![555368c66572553862ed1d80a7e6086d.png](https://img-blog.csdnimg.cn/img_convert/555368c66572553862ed1d80a7e6086d.png)
从上述过程可以看出,十进制数转换为八进制数输出时,符合“后进先出”的规则,与栈的操作是一样的。
对于任意一个非负十进制数,打印其对应的八进制数,代码示意如下:
void ConvertDecToOct(uint8 DecNumber)
{
InitStack(); /* 构造空栈 */
while(DecNumber)
{
Push(S,DecNumber % 8);
DecNumber = DecNumber / 8;
}
while(!isStackEmpty(S))
{
Pop(S,OctNumber);
printf("%d",OctNumber);
}
}
更多文章欢迎订阅公众号:进击的程序喵(swdesigner789)