提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
栈
栈(stack)是限制插入和删除只能在线性表的同一端进行一种特殊的线性表。允许插入和删除的一端称为变化端,称为栈顶,通常用一个指针Top指向栈顶位置,另一个固定端称为栈底,通常用一个Bottom指向它。当表中没有元素时称为空栈。
提示:以下是本篇文章正文内容,下面案例可供参考
一、栈的定义
栈的基本操作:
二、栈常见考题:
题目图解:
三、栈的顺序存储实现:
栈的顺序结构代码声明:
代码实现如下:
#include<stdio.h>
#include<string.h>
#define MAXSIZE 256
typedef int ElemType;
typedef struct SNode
{
ElemType data[MAXSIZE]; //用数组存储顺序表中的元素
int top; //栈顶指针的位置 栈的长度为top+1 栈从0开始
}SeqStack,*PSeqStack;
//栈的初始化操作
void InitStack(PSeqStack SS);
//销毁栈
void DestroyStack(PSeqStack SS);
//清空栈
void clear(PSeqStack SS);
//元素入栈,返回值:0-失败,1-成功
int PushStack(PSeqStack SS,ElemType *ee);
//元素出栈,返回值:0-失败,1-成功
int PopStack(PSeqStack SS,ElemType *ee);
// 求顺序栈的长度,返回值:栈SS中元素的个数。
int Length(PSeqStack SS);
// 判断顺序栈是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PSeqStack SS);
// 判断顺序栈是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqStack SS);
// 打印顺序栈中全部的元素。
void PrintStack(PSeqStack SS);
// 获取栈顶元素,返回值:0-失败;1-成功。
// 只查看栈顶元素的值,元素不出栈。
int GetTop(PSeqStack SS, ElemType *ee);
int main()
{
SeqStack SS; //声明栈
InitStack(&SS);
printf("top=%d,SS.data[10]=%d\n",SS.top,SS.data[10]);
printf("依次将元素 1,2,3,4,6,7,8,9,10入栈\n");
ElemType ee;
ee=1; PushStack(&SS,&ee);
ee=2; PushStack(&SS,&ee);
ee=3; PushStack(&SS,&ee);
ee=4; PushStack(&SS,&ee);
ee=5; PushStack(&SS,&ee);
ee=6; PushStack(&SS,&ee);
ee=7; PushStack(&SS,&ee);
ee=8; PushStack(&SS,&ee);
ee=9; PushStack(&SS,&ee);
ee=10; PushStack(&SS,&ee);
PrintStack(&SS);
printf("栈的长度为:%d\n",Length(&SS));
//查看栈顶元素的值,元素不出栈。
if (GetTop(&SS,&ee)==1) printf("栈顶的元素值为%d\n",ee);
PrintStack(&SS);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (PopStack(&SS,&ee)==1) printf("出栈的元素值为%d\n",ee);
return 0;
}
//栈的初始化操作
void InitStack(PSeqStack SS)
{
clear(SS);
return ;
}
void Destroy(PSeqStack SS)
{
return ;
}
//清空栈
void clear(PSeqStack SS)
{
if(SS==NULL){printf("栈不存在。\n");return ;}
SS->top=-1;
memset(SS->data,0,sizeof(SS->data));
}
//元素入栈,返回值:0-失败,1-成功
int PushStack(PSeqStack SS,ElemType *ee)
{
if(SS==NULL ||ee==NULL){printf("栈不存在或者元素不存在。\n");return 0;}
if(SS->top+1>MAXSIZE)
{
printf("栈满,无法入栈。\n");return 0;
}
SS->top++;
memcpy(&SS->data[SS->top],ee,sizeof(ElemType)); // 用数组的下标访问。
return 1;
}
//元素出栈,返回值:0-失败,1-成功
int PopStack(PSeqStack SS,ElemType *ee)
{
if(SS==NULL ||ee==NULL){printf("栈不存在者元素不存在。\n");return 0;}
if (SS->top == -1) { printf("栈为空。\n"); return 0; }
memcpy(ee,&SS->data[SS->top],sizeof(ElemType)); // 用数组的下标访问。
SS->top--;
return 1;
}
// 求顺序栈的长度,返回值:栈SS中元素的个数。
int Length(PSeqStack SS)
{
if(SS==NULL){printf("栈不存在。\n");return -1;}
return (SS->top+1);
}
// 判断顺序栈是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PSeqStack SS)
{
if(SS==NULL){printf("栈不存在。\n");return 0;}
if(SS->top==-1)return 1;
return 0;
}
// 判断顺序栈是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqStack SS)
{
if(SS==NULL){printf("栈不存在。\n");return 0;}
if(SS->top+1 >= MAXSIZE)return 1;
return 0;
}
// 打印顺序栈中全部的元素。
void PrintStack(PSeqStack SS)
{
if(SS==NULL){printf("栈不存在。\n");return ;}
if (SS->top == -1) { printf("栈为空。\n"); return; }
int ii=SS->top;
while( ii>=0 )
{
printf("%-3d ",SS->data[ii]);
ii--;
}
printf("\n");
}
// 获取栈顶元素,返回值:0-失败;1-成功。
// 只查看栈顶元素的值,元素不出栈。
int GetTop(PSeqStack SS, ElemType *ee)
{
if(SS==NULL ||ee==NULL){printf("栈不存在者元素不存在。\n");return 0;}
if( IsEmpty(SS) ){ printf("栈为空。\n"); return 0; }
memcpy(ee,&SS->data[SS->top],sizeof(ElemType)); // 用数组的下标访问。
return 1;
}
四、链式栈存储实现:
链式栈的存储结构:
typedef int ElemType; // 自定义链栈的数据元素为整数。
typedef struct SNode
{
ElemType data; // 链栈中的元素。
struct SNode *next; // 指向下一个结点的指针。
}SNode,*LinkStack;
下面是链式的代码实现,main函数中加入了一些测试实例:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int ElemType; // 自定义链栈的数据元素为整数。
typedef struct SNode
{
ElemType data; // 链栈中的元素。
struct SNode *next; // 指向下一个结点的指针。
}SNode,*LinkStack;
// 链栈SS的初始化操作,分配头结点,返回头结点的地址。
SNode *InitStack();
// 销毁链栈SS。
void DestroyStack(LinkStack SS);
// 元素入栈,返回值:0-失败;1-成功。
int Push(LinkStack SS, ElemType *ee);
// 元素出栈,返回值:0-失败;1-成功。
int Pop(LinkStack SS, ElemType *ee);
// 求链栈的长度,返回值:栈SS中元素的个数。
int Length(LinkStack SS);
// 清空链栈。
void Clear(LinkStack SS);
// 判断链栈是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(LinkStack SS);
// 打印链栈中全部的元素。
void PrintStack(LinkStack SS);
// 获取栈顶元素,返回值:0-失败;1-成功。
// 只查看栈顶元素的值,元素不出栈。
int GetTop(LinkStack SS, ElemType *ee);
int main()
{
LinkStack ss=InitStack();
if(ss==NULL)return 0;
printf("向栈顶插入元素:1,2,3,4,5,6,7,8,9,10。\n");
ElemType ee;
ee=1; Push(ss,&ee);
ee=2; Push(ss,&ee);
ee=3; Push(ss,&ee);
ee=4; Push(ss,&ee);
ee=5; Push(ss,&ee);
ee=6; Push(ss,&ee);
ee=7; Push(ss,&ee);
ee=8; Push(ss,&ee);
ee=9; Push(ss,&ee);
ee=10; Push(ss,&ee);
PrintStack(ss);
printf("栈的长度是%d\n",Length(ss));
if (GetTop(ss,&ee)==1) printf("栈顶的元素值为%d\n",ee);
PrintStack(ss);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (GetTop(ss,&ee)==1) printf("栈顶的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
if (Pop(ss,&ee)==1) printf("出栈的元素值为%d\n",ee);
DestroyStack(ss); ss=0; // 销毁链栈后把SS置为空,防止野指针。
return 0;
}
// 链栈SS的初始化操作,分配头结点,返回头结点的地址。
SNode *InitStack()
{
SNode* head=(SNode*)malloc(sizeof(SNode));
if(head==NULL)return NULL; //内存不够,分配结点失败
head->next=NULL;
return head;
}
// 销毁链栈SS。释放所有结点,包括头结点
void DestroyStack(LinkStack SS)
{
if(SS==NULL){ printf("栈不存在。\n"); return ; }
SNode* tmp=SS;
while(SS!=NULL)
{
tmp=SS->next;
free(SS);
SS=tmp;
}
}
// 元素入栈,返回值:0-失败;1-成功。
int Push(LinkStack SS, ElemType *ee)
{
if(SS==NULL ||ee==NULL ){ printf("栈不存在或者元素不存在。\n"); return 0; }
SNode *top=(SNode*)malloc(sizeof(SNode));
if(top==NULL)return 0;
//将数据元素的值复制给新结点数据域
memcpy(&top->data,ee,sizeof(ElemType));
top->next=SS->next;
SS->next=top;
return 1;
}
// 元素出栈,返回值:0-失败;1-成功。
int Pop(LinkStack SS, ElemType *ee)
{
if(SS==NULL ||ee==NULL ){ printf("栈不存在或者元素不存在。\n"); return 0; }
//栈顶元素
SNode *tmp=SS->next;
if(tmp==NULL){printf("栈为空。\n"); return 0;}
memcpy(ee,&tmp->data,sizeof(ElemType));
SS->next=tmp->next;
free(tmp);
return 1;
}
// 求链栈的长度,返回值:栈SS中元素的个数。
int Length(LinkStack SS)
{
if(SS==NULL){ printf("栈不存在。\n"); return -1; }
SNode* tmp=SS;
int len=0;
while(tmp->next!=NULL)
{
tmp=tmp->next;
len++;
}
return len;
}
// 清空链栈。释放除了头结点以外所有结点
void Clear(LinkStack SS)
{
if(SS==NULL){ printf("栈不存在。\n"); return ; }
SNode *tmp=SS->next;
while(SS!=NULL)
{
tmp=tmp->next;
free(SS);
SS=tmp;
}
return ;
}
// 判断链栈是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(LinkStack SS)
{
if(SS==NULL){ printf("栈不存在。\n"); return 0; }
if(SS->next==NULL)return 0;
return 1;
}
// 打印链栈中全部的元素。
void PrintStack(LinkStack SS)
{
if(SS==NULL){printf("栈不存在。\n");return ;}
SS=SS->next;
while(SS!=NULL)
{
printf("%3d ",SS->data);
SS=SS->next;
}
printf("\n");
}
// 获取栈顶元素,返回值:0-失败;1-成功。
// 只查看栈顶元素的值,元素不出栈。
int GetTop(LinkStack SS, ElemType *ee)
{
if(SS==NULL){printf("栈不存在。\n");return 0;}
SNode *top=SS->next; //栈顶指针
if(top==NULL){printf("栈空。\n");return 0;}
memcpy(ee,&top->data,sizeof(ElemType));
return 1;
}
总结
相比于单链表,栈的实现显得简单许多,所以只要大家掌握了单链表的代码,完成这章节内容应该相当容易;大家多复习复习单链吧。