栈是一种常见的数据结构,它的特点是先进后出(Last In First Out,LIFO),类似于我们平时用的一个栈子,一次只能放一个物品,后放的物品会覆盖之前放的物品。在计算机中,栈是一种非常重要的数据结构,用来实现函数调用、表达式求值等功能。
C语言中,栈可以用数组实现,也可以用链表实现。下面我们分别介绍一下这两种实现方法。
一. 用顺序存储结构实现栈
用顺序存储结构实现栈的方法比较简单,只需要定义一个数组和一个变量来记录栈顶的位置即可。具体实现如下:
#define MAXSIZE 100 //定义栈的最大长度
typedef struct {
int data[MAXSIZE]; //用数组存储栈中元素
int top; //记录栈顶的位置
} Stack;
初始化栈
void InitStack(Stack *s) {
s->top = -1;
}
//判断栈是否为空
int IsEmpty(Stack *s) {
return s->top == -1;
}
//判断栈是否已满
int IsFull(Stack *s) {
return s->top == MAXSIZE-1;
}
//入栈操作
int Push(Stack *s, int x) {
if (IsFull(s)) {
printf("Stack is full!\n");
return 0;
}
s->data[++s->top] = x;
return 1;
}
//出栈操作
int Pop(Stack *s, int *x) {
if (IsEmpty(s)) {
printf("Stack is empty!\n");
return 0;
}
*x = s->data[s->top--];
return 1;
}
//获取栈顶元素
int GetTop(Stack *s, int *x) {
if (IsEmpty(s)) {
printf("Stack is empty!\n");
return 0;
}
*x = s->data[s->top];
return 1;
}
二. 用链表实现栈
用链表实现栈的方法比较灵活,可以随时插入和删除节点,不需要考虑栈满的问题。具体实现如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
typedef struct SNode
{
int data;
struct SNode* next;
}*StackLink, Snode;
void InitStack(StackLink* SL)
{
(*SL) = (Snode*)malloc(sizeof(Snode));
}
void PushStack(StackLink* SL)
{
int input = 0;
Snode* s;
Snode* sl;
sl = (*SL);
printf("请输入一个数(输入0停止输入:->)");
scanf("%d", &input);
while (input)
{
printf("入栈:->");
printf("%d ", input);
s = (Snode*)malloc(sizeof(Snode));
if (s == NULL)
{
printf("内存分配失败\n");
}
if (!sl)
{
sl->next = s;
s->next = NULL;
}
s->data = input;
s->next = sl->next;
sl->next = s;
printf("请输入一个数(输入0停止输入:->)");
scanf("%d", &input);
}
}
void Print_stack(StackLink* SL)
{
if (!(*SL))
{
printf("the stack is empty\n");
}
else
{
while ((*SL))
{
(*SL) = (*SL)->next;
printf("%d ", (*SL)->data);
}
}
printf("\n");
}
void PopStack(StackLink* SL)//x返回出栈的元素
{
if (!((*SL)->next))
{
printf("the Stack is empty\n");
}
while ((*SL)->next)
{
free((*SL));
(*SL) = (*SL)->next;
}
}
int main()
{
StackLink SL;
InitStack(&SL);
PushStack(&SL);
printf("出栈:\n");
Print_stack(&SL);
PopStack(&SL);
return 0;
}
1.运行测试
三.十进制转二进制数
十进制转二进制,八进制,十六进制数,都是利用除权取余逆序读入法
正好符合栈先进后出的特性,因为我们这里使用的是单链表,直接使用头插法即可完成
图解
代码实现
#define _CRT_SECURE_NO_WARNINGS 1
//
#include<stdio.h>
#include<malloc.h>
typedef struct Snode
{
int val;
struct Snode* next;
struct Snode* front;
}Snode, *StackLink;
void initStackLink(StackLink* SL)
{
(*SL) = (Snode*)malloc(sizeof(Snode));
}
Snode* PushStack(StackLink* SL,int* SizeNum)
{
int tran_num = 0;
printf("请输入一个数->");
scanf("%d", &tran_num);
Snode* s;
Snode* r;
r = (*SL);
printf("进栈:->\t");
while (tran_num)
{
int input = tran_num % 2;
s = (Snode*)malloc(sizeof(Snode));
s->val = input;
printf("%d", s->val);
s->next = NULL;
r->next = s;
s->front = r;
r = s;
(*SizeNum)++;
tran_num = (tran_num) / 2;
}
printf("\n");
return r;
}
int PopStack(StackLink* tail,int* SizeNum)
{
if ((*tail) == NULL)
return 0;
else
{
printf("出栈:->\t");
while ((*tail)&&(*SizeNum))
{
printf("%d", (*tail)->val);
(*tail) = (*tail)->front;
(*SizeNum)--;
}
printf("\n");
return 1;
}
}
int main()
{
StackLink SL;
int SizeNum = 0;//二进制位数
initStackLink(&SL);
Snode* tail = PushStack(&SL,&SizeNum);
int ret = PopStack(&tail,&SizeNum);//判断栈是否为空
}
四.括号匹配案例
#include<string.h>
#include<stdio.h>
#define MAX_SIZE 100
typedef struct StackList
{
int top1;//表示原始栈顶
int top2;//新入栈元素栈顶
char LetterArr1[MAX_SIZE];//原始
char LetterArr2[MAX_SIZE];//新
}stacklist,Snode;
//括号匹配问题
void InitStack(stacklist* SL)
{
SL->top1 = -1;
SL->top2 = -1;
}
void creat_Arr(stacklist* SL)
{
printf("输入括号字符串:([{)]}===>");
scanf("%s", SL->LetterArr1);
//printf("%s", SL->LetterArr1);
}
void brackets_mate(stacklist* SL)
{
int size = strlen(SL->LetterArr1);
for (int i = 0; i < size; i++)
{
//printf("i = %d\n", i);
if (SL->LetterArr1[i] == '(' || SL->LetterArr1[i] == '[' || SL->LetterArr1[i] == '{')
{
//printf("%c\n", SL->LetterArr1[i]);
SL->LetterArr2[++(SL->top2)] = SL->LetterArr1[i];
//printf("top2 = %d\n", SL->top2);
}
else
{
if (SL->top2==-1)
{
printf("The stack is empty\n");
}
//printf("top2 = %d\n", SL->top2);
char Topelem = SL->LetterArr2[SL->top2];
//printf("size = %d\n", size);
if ((SL->LetterArr1[i] ==')' && '(' == Topelem) || (SL->LetterArr1[i] == ']' && '[' == Topelem) || (SL->LetterArr1[i] == '}' && '{' == Topelem))
{
//printf("newtop2 = %d\n", SL->top2);
SL->top2--;
//printf("newtop2 = %d\n", SL->top2);
}
else
{
printf("the brackets mate defeat\n");
break;
}
}
}
if (SL->top2!=-1)
{
printf("The brackets mate defeat\n");
}
else
{
printf("The brackets mate success\n");
}
}
int main()
{
stacklist SL;
InitStack(&SL);
creat_Arr(&SL);
brackets_mate(&SL);
return 0;
}
五.总结
以上是用C语言实现栈的两种方法,读者可以根据需要选择适合自己的方法。在实际应用中,栈可以用来实现表达式求值、括号匹配,十进制数转八,二,十六进制数等功能,具有广泛的应用价值。