顺序栈
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 30
typedef int ElemType;
//顺序栈的结构定义
typedef struct{
ElemType data[MAXSIZE]; //数组
int top;
}SeqStack;
//栈的初始化
SeqStack *InitStack(){
SeqStack *s;
s=(SeqStack*)malloc(sizeof(SeqStack));
s->top=-1;//top定在-1 //如果是0的话,表示索引到零号元素
return s;
}
//判空栈
//返回1表示是空栈 , 返回0表示不是空栈
int Empty(SeqStack *s){
if(s->top==-1)
return 1;
else
return 0;
}
//入栈(push)
//将元素x压入栈中
//返回0表示栈满 , 返回1表示入栈成功
int Push(SeqStack *s,ElemType x){ //传入的参数是一个指向栈的结构体指针和一个要存入栈顶的元素
if(s->top==MAXSIZE-1){
return 0;
}else{
s->top++;
s->data[s->top]=x; //[s->top]是指数组的第几个元素
return 1;
}
}
//出栈 (popup)
//注意此时的参数需要带*,需要对调用地址操作
//返回0表示空栈了,返回1表示出栈成功
int Pop(SeqStack* s,ElemType *x){
if(s->top==-1){
return 0;
}else{
*x=s->data[s->top];
s->top--;
return 1;
}
}
//取出栈顶元素
//返回0表示当前栈为空栈,否则返回栈顶元素的值
ElemType GetTop(SeqStack* s){
if(s->top==-1){
return 0;
}else{
return (s->data[s->top]);
}
}
int main(){
SeqStack* s=InitStack();//初始化栈
printf("%d\n",Push(s,3));
printf("%d\n",Push(s,4));
printf("%d\n",GetTop(s));
int i;
printf("%d\n",Pop(s,&i)); //在函数中对i赋值改变,因为传递的是地址,所以函数中赋值改变后在主函数中依然起作用
printf("%d",i);
// printf("%d\n",GetTop(s));
// printf("%d\n",Empty(s));
// printf("%d\n",Pop(s,&i));
// printf("%d\n",Empty(s));
}
须注意的地方都已在代码中注释出
链栈
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
//链栈的结构定义
//每个结点
typedef struct StackNode{
ElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr; //pointer指针 stack栈;堆栈 linked list 链表
//结构体变量,结构体指针变量
//top结构体
typedef struct{
LinkStackPtr top; //结构体指针
//int count;//记录线性表的长度
}LinkStack;
//结构体变量
//栈的初始化
LinkStack* InitStack(){
LinkStack* s;
s=(LinkStack *)malloc(sizeof(LinkStack));
//s->count=0;
s->top=NULL;
return s;
}
//判空栈
int Empty(LinkStack *s){
if(s->top==NULL){
return 1;
//返回1表示空栈
}else{
return 0;
//返回0表示不为空栈
}
}
//入栈
int Push(LinkStack *s,ElemType x){
LinkStackPtr p; //结构体指针
if((p=(LinkStackPtr)malloc(sizeof(StackNode)))==NULL){ //申请的空间是第一个结构体大小的一块空间
return 0;
//返回0表示无内存空间了
}
p->data=x;
p->next=s->top; //p的next指向原来的栈顶top (top和p是同类型的结构体数据,因此可以进行整体赋值操作)(top不仅仅只是一个指针)
s->top=p; //栈顶top指向新节点p
return 1;
//返回1表示入栈成功
}
//出栈
int Pop(LinkStack *s,ElemType *x){
LinkStackPtr p; //定义一个结构体指针
if(Empty(s)){
return 0;
//返回0表示此栈为空栈
}else{
p=s->top;//p指针和top指针指向同一块地址 , 即此时栈顶的地址
*x=p->data; //将栈顶元素中的数据赋给指针x
s->top=p->next;//将栈顶指向下一个
free(p);//将p,即原来的栈顶free掉
return 1;
//返回1表示出栈成功
}
}
//取出栈顶元素
ElemType GetTop(LinkStack* s){
if(s->top==NULL){
return 0;
//返回0表示空栈了
}else{
return s->top->data;//
}
}
int main(){
LinkStack* s=InitStack();
Push(s,4);
Push(s,5);
printf("%d\n",GetTop(s));
int i;
printf("%d\n",Pop(s,&i));
printf("%d\n",GetTop(s));
printf("%d\n",Empty(s));
printf("%d\n",Pop(s,&i));
printf("%d\n",Empty(s));
}
须注意的地方都已在代码中注释出
队列的知识点
-
队列定义
队列(Queue)是一种先进先出的线性表简称FIFO(First In First Out)。允许插入的一端称为队尾,允许删除的一端称为队头。 -
入队列。其实就是在队尾追加一个元素,并不需要移动任何元素。
-
出队列。出去一个元素后,队列中的剩余其他所有元素都得向前移动,以保证队头不为空。
-
计算队列长度。首先定义两个指针front和rear,front指针指向队头元素,rear指针指向队尾元素的下一个位置,这样的话当front等于rear时,此队列为空队列。(队列的最大尺寸为QueueSize)
计算长度的通式为:(rear - front + QueueSize)% QueueSize -
队列基本分为顺序队列,循环队列,链队列。
-
循环队列需要事先申请好空间,使用期间不释放。因此必须拥有一个固定的长度,所以会有元素个数,空间的浪费。
-
链队列则每次申请空间,不需要了在释放掉,不会造成元素个数,空间的浪费,但每次申请释放空间也会浪费一定的时间。所以在空间上,链队列更为灵活一些。