栈是数据结构中较为简单的结构体,是一种操作受到限制的线性表。但简单不代表没用,毕竟数组很简单。但谁敢说数组没用呢?
栈的思想
- 栈是一个先进后出的结构,类似于堆盘子,先放到地上的盘子最后被取走(默认只能取走一个盘子)
- 栈其实就是操作受限的线性表,只有一个口,每一次操作时,这个口可以当出口也可以当入口
- 例如:水桶注入水时,水桶的头当做入口,倒水时,水桶的头当做出口
栈的图解
- 这是一个空栈,只有上面是入口和出口
- 放入一个元素a
- 接着依次放入元素b、c
- 取出一个元素,由栈只有一个口的特点可以知道取出了元素c
- 再次放入一个元素d
根据图解,可以轻易的看出:栈的基本操作只有两个
- 入栈
- 出栈
样子长得十分像一个水桶
但是如果栈已经放满了,就像水桶装满了水一样,不能再放水了,即不能再进行入栈操作,所以要在每次入栈前判断栈满的情况。同理,出栈之前,栈中必须有数据,不然就出现要么空指针,要么野指针。都不是我们想要的结果,所以出栈前要判断栈是否为空。
栈的定义
顺序表实现栈:
typedef int DataType; //数据类型
typedef struct Stack
{
DataType* _arr; //顺序表实现栈
size_t _size; //有效元素的个数
size_t _capacity; //容量
} Stack;
栈的初始化和销毁:Init、Destroy
void Init(Stack* st)
{
st->_arr = NULL;
st->_size = st->_capacity = 0;
}
void Destroy(Stack* st)
{
if (st->_arr)
{
free(st->_arr);
st->_arr = NULL;
st->_size = st->_capacity = 0;
}
}
栈的四个基本操作:Push、Pop、Top、Empty
void Push(Stack* st, DataType val)
{
//扩容
if (st->_size == st->_capacity)
{
size_t new_capacity = st->_capacity == 0 ? 2 : st->_capacity * 2;
DataType* tmp = (DataType*)malloc(sizeof(DataType) * new_capacity);
if (st->_arr)
{
memcpy(tmp, st->_arr, sizeof(DataType) * st->_size);
}
st->_arr = tmp;
st->_capacity = new_capacity;
}
st->_arr[st->_size++] = val;
}
void Pop(Stack* st)
{
assert(st->_arr != NULL);
--st->_size;
}
DataType Top(Stack* st)
{
assert(st->_arr != NULL);
return st->_arr[st->_size - 1];
}
int Empty(Stack* st)
{
if (st->_size == 0)
{
return 1;
}
return 0;
}
完整代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef int DataType; //数据类型
typedef struct Stack
{
DataType* _arr; //顺序表实现栈
size_t _size; //有效元素的个数
size_t _capacity; //容量
} Stack;
void Init(Stack* st)
{
st->_arr = NULL;
st->_size = st->_capacity = 0;
}
void Push(Stack* st, DataType val)
{
//扩容
if (st->_size == st->_capacity)
{
size_t new_capacity = st->_capacity == 0 ? 2 : st->_capacity * 2;
DataType* tmp = (DataType*)malloc(sizeof(DataType) * new_capacity);
if (st->_arr)
{
memcpy(tmp, st->_arr, sizeof(DataType) * st->_size);
}
st->_arr = tmp;
st->_capacity = new_capacity;
}
st->_arr[st->_size++] = val;
}
void Pop(Stack* st)
{
assert(st->_arr != NULL);
--st->_size;
}
DataType Top(Stack* st)
{
assert(st->_arr != NULL);
return st->_arr[st->_size - 1];
}
int Empty(Stack* st)
{
if (st->_size == 0)
{
return 1;
}
return 0;
}
size_t Size(Stack* st)
{
return st->_size;
}
void Destroy(Stack* st)
{
if (st->_arr)
{
free(st->_arr);
st->_arr = NULL;
st->_size = st->_capacity = 0;
}
}
测试用例
void Test()
{
Stack st;
Init(&st);
Push(&st, 1);
Push(&st, 2);
Push(&st, 3);
Push(&st, 4);
Push(&st, 5);
while (!Empty(&st))
{
printf("%d ", Top(&st));
Pop(&st);
}
printf("\n");
Destroy(&st);
}