栈
概念
栈是一种特殊的线性表,数据进出栈遵循“后进先出”的原则(last in first out)。
压栈:是指数据从栈顶进入
出栈:是指数据从栈顶出去
栈的实现思路
可以用顺序表和链表两种形式
1)用顺序表
可以考虑用动态和静态两种,一般会选择动态,可以进行扩容处理,有利于高效利用空间
2)用链表
这时候就要考虑链表的形式以及栈顶位置的选取(会影响时间复杂度),如果用单链表,若栈顶选择链表尾,保存尾指针,入栈可以采取尾插形式,出栈就必须先找到尾指针的前一个,需要遍历链表,时间复杂度较高;若栈顶选择头指针,入栈可以采取头插,出栈可以采取尾插,时间复杂度和空间复杂度都比较高。如果用双向链表,也可以实现栈的相应功能,但是并不是最优的。
栈的代码实现
先创建一个新的工程Stack,创建头文件Stack.h(放函数声明),源文件Stack.c(放函数定义),test.c(测试文件)
先在Stack.h中写上与栈有关的结构体,用动态顺序表来实现
typedef int STDataType;
#define m 3
typedef struct Stack
{
STDataType* a;//动态数组->存放数据
STDataType pop;//栈顶
int capacity;//数组容量大小
}ST;
【1】初始化函数STInit
void STInit(ST* p)
{
STDataType* q= (STDataType*)malloc(sizeof(STDataType)*m);
if (q == NULL)
{
perror("malloc fail!");
return;
}
p->a = q;
p->pop = 0;//指向栈顶元素的下一个元素
p->capacity = m;
}
【2】销毁函数STDestroy
void STDestroy(ST* p)
{
assert(p);
free(p->a);
p->a = NULL;
}
【3】入栈函数STPush
void STPush(ST* p, STDataType x)
{
assert(p);
if (p->pop == p->capacity)
{
STDataType* q = (STDataType*)realloc(p->a, sizeof(STDataType)* p->capacity * 2);
if (q == NULL)
{
perror("mallo fail!");
return;
}
else
{
p->a = q;
p->capacity *= 2;
}
}
p->a[p->pop] = x;
p->pop++;
}
【4】出栈函数STPop
void STPop(ST* p)
{
assert(p);
assert(!STempety(p));//非空为真,那么STempty为假
p->pop--;
}
【5】找栈顶元素函数STTop
STDataType STTop(ST* p)
{
assert(p);
return p->a[p->pop - 1];
}
【6】判断是否为空函数STempety
bool STempety(ST* p)
{
return p->pop == 0 ? 1 : 0;//pop==0表示没有元素
}
【7】查询栈中元素个数函数STSize
int STSize(ST* p)
{
assert(p);
return p->pop - 1;
}
代码完整表示:
Stack.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include<assert.h>
typedef int STDataType;
#define m 3
typedef struct Stack
{
STDataType* a;//动态数组->存放数据
STDataType pop;//栈顶
int capacity;//数组容量大小
}ST;
void STInit(ST* p);
void STDestroy(ST* p);
void STPush(ST* p, STDataType x);
void STPop(ST* p);//也可以考虑将STop与STTop合并写成一个函数
STDataType STTop(ST* p);
bool STempety(ST* p);
int STSize(ST* p);
Stack.c
#include"Stack.h"
void STInit(ST* p)
{
STDataType* q= (STDataType*)malloc(sizeof(STDataType)*m);
if (q == NULL)
{
perror("malloc fail!");
return;
}
p->a = q;
p->pop = 0;//指向栈顶元素的下一个元素
p->capacity = m;
}
void STDestroy(ST* p)
{
assert(p);
free(p->a);
p->a = NULL;
}
void STPush(ST* p, STDataType x)
{
assert(p);
if (p->pop == p->capacity)
{
STDataType* q = (STDataType*)realloc(p->a, sizeof(STDataType)* p->capacity * 2);
if (q == NULL)
{
perror("mallo fail!");
return;
}
else
{
p->a = q;
p->capacity *= 2;
}
}
p->a[p->pop] = x;
p->pop++;
}
void STPop(ST* p)
{
assert(p);
assert(!STempety(p));//非空为真,那么STempty为假
p->pop--;
}
STDataType STTop(ST* p)
{
assert(p);
return p->a[p->pop - 1];
}
bool STempety(ST* p)
{
return p->pop == 0 ? 1 : 0;//pop==0表示没有元素
}
int STSize(ST* p)
{
assert(p);
return p->pop - 1;
}
test.c
#include"Stack.h"
void test1()
{
ST p;
STInit(&p);
STPush(&p, 1);
STPop(&p);
printf("1 ");
STPush(&p, 2);
STPush(&p, 3);
STPop(&p);
printf("3 ");
STPush(&p, 4);
STPush(&p, 5);
STPush(&p, 6);
while (!STempety(&p))
{
printf("%d ",STTop(&p));
STPop(&p);
}
}
int main()
{
test1();
return 0;
}