栈:Stack
栈(Stack)是数据结构中的一种基本数据类型,它是一种特殊的线性表,其数据元素的插入和删除操作只能在一端进行。栈的特点是“先进后出”(Last In First Out,简称LIFO),也就是说最后插入的元素首先被删除。
栈具有两个基本操作,即入栈和出栈。入栈(Push)操作将一个新元素添加到栈的顶端,出栈(Pop)操作将栈顶的元素删除并返回其值。
栈可以用数组或链表实现。在使用数组实现栈时,需要定义一个栈顶指针来指示栈顶元素的位置,插入元素时栈顶指针加1,删除元素时栈顶指针减1。在使用链表实现栈时,每个节点包含一个数据元素和一个指向下一个节点的指针,将新元素插入时将其作为链表的新头节点,删除元素时将头节点删除。
除了基本的入栈和出栈操作外,栈还可以进行其他一些操作,如获取栈顶元素(Top),判断栈是否为空(isEmpty)等。
栈的应用非常广泛,常见的应用场景包括:括号匹配、计算表达式、图的深度优先搜索等。
链式栈
链式栈是一种使用链表实现的栈。
链式栈的结构由多个节点组成,每个节点包含一个数据元素和指向下一个节点的指针。栈顶指针指向链表的第一个节点,栈底指针指向链表的最后一个节点。
链式栈的操作包括入栈和出栈两种操作:
-
入栈:将一个新的元素添加到栈顶。入栈操作需要创建一个新的节点,并将其指针指向当前的栈顶节点,然后更新栈顶指针。
-
出栈:从栈顶移除一个元素。出栈操作需要将栈顶指针指向下一个节点,并释放当前的栈顶节点。
链式栈的特点是可以动态调整大小,不受固定容量的限制。但由于使用了指针,会消耗额外的内存空间。
链式栈的时间复杂度为O(1),即常数时间,因为入栈和出栈操作只需要更新栈顶指针和创建/释放节点,不涉及遍历整个栈。
链式栈的应用场景包括但不限于:括号匹配、表达式求值、迷宫求解等。
例题
链栈,节存储学生信息(年龄,分数,姓名)三级引用。
1、建立学生信息结构体,将data改为学生信息结构体类型。
2、循环入栈和入队。
主函数:
#include <myhead.h>
#define MAX 4
typedef struct
{
char name[20];
int age;
int score;
}stu;
typedef struct node
{
stu data;
struct node *next;
}Node,*Pnode;
typedef struct
{
int len;
Node *top;
}Stack,*Pstack;
Pstack creat_stack()
{
Pstack p = malloc(sizeof(Stack));//申请的栈顶指针节点
if(p==NULL)
{
printf("创建链栈失败\n");
return NULL;
}
p->len = 0;//初始化
p->top = NULL;
return p;//返回栈顶节点
}
int push_stack(Pstack L,stu e)//入栈
{
if(L==NULL)
{
printf("链栈不存在\n");
return -1;
}
Node *p = malloc(sizeof(Node));//生成正常的新节点
p->data =e;
p->next = L->top;
L->top = p;//栈顶指针指向新节点
L->len++;//计数器+1
printf("入栈成功\n");
return 0;
}
int output_stack(Pstack L)
{
if(L==NULL||L->len==0)
{
printf("栈不存在或者为空\n");
return -1;
}
int i;
Node* t = L->top;//指向第一个正常节点(栈顶)
for(i = 0;i<L->len;i++)//从栈顶输出到栈底
{
printf("姓名:%s\t年龄:%d\t分数:%d\t",t->data.name,t->data.age,t->data.score);
t = t->next;
printf("\n");
}
return 0;
}
/*
int pop_stack(Pstack L)//出栈
{
if(L==NULL||L->len==0)
{
printf("栈不存在或者为空\n");
return -1;
}
Node * Q = L->top;//保留要出栈的节点
printf("出栈节点:%d\n",Q->data.name);
L->top = Q->next;//栈顶指针下移一位
L->len--;
free(Q);
Q=NULL;
printf("出栈成功\n");
return 0;
}
*/
int destroy_stack(Pstack L)
{
Node * t;
while(t!=NULL)
{
t = L->top;//指向第一个正常节点
L->top = L->top->next;//向后移动top
free(t);
}
free(L);
L=NULL;
t = NULL;
printf("释放节点成功\n");
return 0;
}
int main(int argc, const char *argv[])
{
/*stu students[4] = {
{"王", 20, 89},
{"刘", 22, 92},
{"孙", 19, 85},
{"李", 21, 88}
};*/
stu students[MAX];
int j;
for(j=0;j<MAX;j++)
{
printf("请输入第%d位学生姓名,年龄,成绩: ",j+1);
scanf("%s%d%d",students[j].name,&students[j].age,&students[j].score);
printf("\n");
}
Pstack L=creat_stack();
int i;
for(i=0;i<4;i++)
{
push_stack(L,students[i]);
}
output_stack(L);
destroy_stack(L);
return 0;
}
运行结果:
请输入第1位学生姓名,年龄,成绩: 李 21 88
请输入第2位学生姓名,年龄,成绩: 孙 19 85
请输入第3位学生姓名,年龄,成绩: 刘 22 92
请输入第4位学生姓名,年龄,成绩: 王 20 89
入栈成功
入栈成功
入栈成功
入栈成功
姓名:王 年龄:20 分数:89
姓名:刘 年龄:22 分数:92
姓名:孙 年龄:19 分数:85
姓名:李 年龄:21 分数:88
释放节点成功