栈的基本概念:
栈(stack)是一种先进后出(后进先出)的数据结构;有栈顶(可以进行元素的插入和删除)和栈底
栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为
对于栈的理解:
你可以将栈理解为一个较大的且只有一个出口的密闭空间,把里边的东西理解为存储的元素(当然,这些元素不能够自由移动)。例如:向弹夹里压子弹
![](https://i-blog.csdnimg.cn/blog_migrate/965cb72eb045c54ed5036d3d0884edbc.png)
![](https://i-blog.csdnimg.cn/blog_migrate/122b3c116638a2b1fee5095e57130616.png)
栈的顺序存储:
概念:所谓栈的顺序存储,就是利用数组模拟出栈的先进后出的数据结构
栈的顺序存储(使用数组)
数组的首地址做栈顶好还是做栈底好?
答:做栈底比较好,因为 栈顶要进行元素的插入和删除操作,所以数组尾部更适合比较频繁的插入和删除
栈的结构体:
typedef struct Stack{
int data[MAX]; //数据域
int size; //栈的大小
}Stack,*SeqStack;
栈的初始化:
SeqStack create(){
//创建栈相当于动态开辟一个数组出来
SeqStack p=(Stack*)malloc(sizeof(Stack));
if(p==NULL){
return NULL;
}
//初始化 栈的大小
p->size=0;
//初始化 栈中的元素
for(int i=0;i<MAX;i++){
p->data[i]=0;
}
return p;
}
入栈:
void push(SeqStack stack,int data){
if(stack==NULL){
return;
}
//入栈需要判断栈是否已满
if(stack->size==MAX){
printf("栈已满!\n");
return;
}
//stack->size 栈的大小就是 我们插入元素的下一个位置
stack->data[stack->size]=data;
//改变栈的大小
stack->size++;//栈的大小随着元素的插入和删除改变
}
入栈需要注意 栈是否为空 栈是否已满;
出栈:
void pop(SeqStack stack){
if(stack==NULL){
return;
}
if(stack->size==0){
printf("栈已空!\n");
return;
}
//删除一个元素
stack->data[stack->size-1]=0;
//改变栈的大小
stack->size--;
}
出栈 需要注意栈是否不存在 栈是否已空
遍历栈中元素:
void foreachStac(SeqStack stack){
if(stack==NULL){
return;
}
for(int i=0;i<stack->size;i++){
printf("%d",stack->data[i]);
}
}
栈的链式存储(链表):
概念:利用链表模拟出栈的先进后出的数据结构
链表的头结点 做栈顶还是栈底?
答:栈顶 因为链表的头结点端 可以更方便的进行 元素的插入(头插法)和删除(头节点做前驱)
栈链式存储结构体:
//结点结构体
typedef struct Node{
int data;
struct Node *next;
}Node;
//栈的结构体
typedef struct stact{
stact Node header; //头结点
int size; //栈的大小 即元素的个数
}Stact,*LinkList;
栈的初始化:
LinkList init_LinkStack(){
//myStack 是指针指向的空间
LinkStack myStack=(Stack *)malloc(sizeof(Stack));
if(myStack==NULL){
return NULL;
}
//初始化长度为 0
myStack->size=0;
//相当于 初始化的是链表的头结点 指针域
myStack->header.next==NULL;
}
入栈:
void push(LinkList stack,int data){
if(stack==NULL){
return;
}
//创建一个节点
Node *p=(Node*)malloc(sizeof(Node));
//给结点数据域 赋值
p->data=data;
//头插法 先连后边
p->next=stack->header.next;
stack->header.next=p;
//改变栈中元素的个数
stack->size++;
}
出栈:
void pop(LinkStack stack){
//判断栈存不存在
if(stack==NULL){
return;
}
//判断栈空
if(stack->size==0){
printf("栈中无元素!\n");
return;
}
//定义一个结点类型指针用作删除 结点
Node *p=stack->header.next;
//头结点连接到删除结点的后边
stack->header.next=p->next;
//释放结点
free(p);
//更新栈大小
stack->size--;
}