栈的概念:
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
链式栈:利用带头结点的单链表实现
栈只能在栈顶进行操作
链式栈的栈顶是第一个数据结点
特点:先进后出
链式栈是一种数据存储结构,可以通过单链表的方式来实现,使用链式栈的优点在于它能够克服用数组实现的顺序栈空间利用率不高的特点,但是需要为每个栈元素分配额外的指针空间用来存放指针域。
先介绍下出入栈的过程:
入栈:
出栈:
以下为全部代码:
liststack.h
#pragma once
typedef struct SNode
{
int data;//数据
struct SNode *next;//存放下一个结点的地址
}SNode,*PLStack;
//初始化
void InitStack(PLStack ps);
//入栈
bool Push(PLStack ps,int val);
//出栈(获取栈顶值并删除)
bool Pop(PLStack ps,int *rtval);
//获取栈顶值但不删除
bool GetTop(PLStack ps,int *rtval);
//获取有效数据的个数
int GetLength(PLStack ps);
//判空
bool IsEmpty(PLStack ps);
//清空
void Clear(PLStack ps);
//摧毁
void Destroy(PLStack ps);
//打印
void Show(PLStack ps);
liststack.cpp
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "liststack.h"
//初始化
void InitStack(PLStack ps)
{
assert(ps != NULL);
ps->next = NULL;
}
//入栈(类似单链表的头插)
bool Push(PLStack ps,int val)
{
assert(ps != NULL);
SNode *p = (SNode *)malloc(sizeof(SNOde));
p->data= val;
p->next = ps->next;
ps->next = p;
return true;
}
//出栈(获取栈顶值并删除)
bool Pop(PLStack ps,int *rtval)
{
assert(ps != NULL);
if(IsEmpty(ps))
{
return false;
}
SNode *p = ps->next;
*rtval = p->data;
ps->next = p->next;
free(p);
return true;
}
//获取栈顶值但不删除
bool GetTop(PLStack ps,int *rtval)
{
assert(ps != NULL);
if(IsEmpty(ps))
{
return false;
}
SNode *p = ps->next;
*rtval = p->data;
return true;
}
//获取有效数据的个数
int GetLength(PLStack ps)
{
int count = 0;
for(SNode *p = ps->next;p != NULL;p = p->next)
{
count ++;
}
return count;
}
//判空
bool IsEmpty(PLStack ps)
{
return ps->next == NULL;
}
//清空
void Clear(PLStack ps)
{
Destroy(ps);
}
//摧毁
void Destroy(PLStack ps)
{
SNode *p;
while(ps->next != NULL)
{
p = ps->next;
ps->next = p->next;
free(p);
}
}
//打印
void Show(PLStack ps)
{
for(SNode *p = ps->next;p != NULL;p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
}
主函数:
#include <stdio.h>
#include <vld.h>//测试内存是否泄露的头文件
#include "liststack.h"
int main()
{
SNode s;
InitStack(&s);//测试初始化
for(int i = 0;i < 15;i++)
{
Push(&s,i);//测试入栈
}
Show(&s);//测试打印
printf("%d\n",GetLength(&s));//测试获取有效数据的个数
int tmp;
GetTop(&s,&tmp);//测试获取栈顶元素的值但不删除
printf("%d\n",tmp);
int tmp1;
while(!IsEmpty(&s))
{
Pop(&s,&tmp1);//测试出栈(获取栈顶元素的值并删除)
printf("%d ",tmp1);
}
Destroy(&s);//测试摧毁
Destroy(&s);
return 0;
}
顺序栈:
顺序栈是栈的顺序实现。顺序栈是指利用顺序存储结构实现的栈。采用地址连续的存储空间(数组)依次存储栈中数据元素,由于人栈和出栈运算都是在栈顶进行,而栈底位置是固定不变的,可以将栈底位置设置在数组空间的起始处;栈顶位置是随入栈和出栈操作而变化的,故需用一个整型变量top来记录当前栈顶元素在数组中的位置
seqstack.h
#pragma once//防止头文件重复引用
//不定长顺序表实现栈
#define INITSIZE 10
typedef struct Stack
{
int *elem;//数据
int top;//栈顶指针 表示当前可以存放数据的下标
int stacksize;//栈的总格子数(容量)
}Stack,*PStack;
//初始化
void InitStack(PStack ps);
//入栈
bool Push(PStack ps,int val);
//获取栈顶值 但不删除
//rtval:输出参数
bool GetTop(PStack ps,int *rtval);
//获取栈顶值并删除
bool Pop(PStack ps,int *rtval);
//获取有效数据个数
int GetLength(PStack ps);
//判空
bool IsEmpty(PStack ps);
//清空
void Clear(PStack ps);
//摧毁
void Destroy(PStack ps);
//打印
void Show(PStack ps);
seqstack.cpp
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "seqstack.h"
//初始化
void InitStack(PStack ps)
{
assert(ps != NULL);
ps->elem = (int *)malloc(sizeof(int)*INITSIZE);
ps->top = 0;
ps->stacksize = INITSIZE;
}
//判满(内部函数)
static bool IsFull(PStack ps)
{
return ps->top == ps->stacksize;
}
//扩容(内部函数)
static void Inc(PStack ps)
{
ps->elem = (int *)realloc(ps->elem,ps->stacksize*2*sizeof(int));
ps->stacksize *= 2;
}
//入栈
bool Push(PStack ps,int val)
{
assert(ps != NULL);
if(IsFull(ps))
{
Inc(ps);
}
ps->elem[ps->top] = val;//ps->elem[ps->top++] = val;
ps->top++;
return true;
}
//获取栈顶值 但不删除
//rtval:输出参数
bool GetTop(PStack ps,int *rtval)
{
if(IsEmpty(ps))
{
return false;
}
*rtval = ps->elem[ps->top-1];
return true;
}
//出栈 :获取栈顶值并删除
bool Pop(PStack ps,int *rtval)
{
if(IsEmpty(ps))
{
return false;
}
*rtval = ps->elem[ps->top-1];
ps->top--;
return true;
}
//获取有效数据个数
int GetLength(PStack ps)
{
return ps->top;
}
//判空
bool IsEmpty(PStack ps)
{
return ps->top == 0;
}
//清空
void Clear(PStack ps)
{
ps->top = 0;
}
//摧毁
void Destroy(PStack ps)
{
free(ps->elem);
ps->elem = NULL;
}
//打印
void Show(PStack ps)
{
for(int i = 0; i < ps->top;i++)
{
printf("%d ",ps->elem[i]);
}
printf("\n");
}
主函数:
#include <stdio.h>
#include <vld.h>//测试内存泄漏的头文件
#include "seqstack.h"
int main()
{
Stack s;
InitStack(&s);//测试初始化
for(int i=0;i<20;i++)
{
Push(&s,i);//测试入栈
}
Show(&s);//测试打印
printf("%d\n",GetLength(&s));//测试获取有效数据的个数
int tmp;
GetTop(&s,&tmp);//测试获取栈顶值 但不删除
printf("%d\n",tmp);
int tmp1;
while(!IsEmpty(&s))
{
Pop(&s,&tmp1);//测试出栈
printf("%d\n",tmp1);
}
Destroy(&s);//测试摧毁
Destroy(&s);
return 0;
}