目录
顺序栈🔗:【栈】顺序栈知识点-内含基本操作及其说明
本文的代码操作实现是带头结点的
一、概念
- 栈的顺序存储叫做顺序栈,栈的链式存储叫做链式栈,简称链栈
- 对于链栈,基本不存在栈满的情况,不用像顺序栈一样判满然后扩容。
- 空战就是链表头结点指向空,即plist->next==NULL
- 顺序栈需要事先确定一个固定的长度,可能会存在内存浪费的问题,但是它的优势是存取时定位很方便,而链栈则要求每个结点有个指针域。但是链栈大小很灵活,最好使用链栈。
- 栈顶的位置由哪端就在哪端决定,发现在栈顶进行插入删除操作,因此栈顶位置在表头
- 头插头删:O(1)
- 尾巴:O(n)
- 链式栈其实就是把顺序表改为链式结构
- 顺序栈:栈顶在尾巴
链式栈:栈顶在头部,但是对外表现得都是top,使用接口时不需要知道是顺序栈还是链式栈
二、基本操作
定义
typedef int ElemType;
typedef struct LStack
{
ElemType data;//数据
struct LStack* next;//后继
}LStack, * PLStack;
初始化
//初始化
void InitStack(PLStack ps)
{
assert(ps->next != NULL);
ps->next = NULL;
}
入栈
//入栈,把val的值插入到栈内
bool Push(PLStack ps, ElemType val)
{ //动态创建
LStack* p = (LStack*)malloc(sizeof(LStack));
assert(p != NULL);
p->data = val;
//把p头插到ps
p->next = ps->next;
ps->next = p;
return true;
}
判空
//判空
bool IsEmpty(PLStack ps)
{
return ps->next == NULL;
}
获取栈顶元素
//获取栈顶元素,且删除栈顶元素
bool Pop(PLStack ps, ElemType* rtval)
{
assert(ps != NULL);
if (IsEmpty(ps))
return false;
*rtval = ps->next->data;//栈顶在头部
return true;
}
获取栈顶元素并删除
//获取栈顶元素,且删除栈顶元素
bool Pop(PLStack ps, ElemType* rtval)
{
assert(ps != NULL);
if (IsEmpty(ps))
return false;
LStack* p = ps->next;
*rtval = p->data;//栈顶在头部
//删除p
ps->next = p->next;
free(p);
return true;
}
获取数据长度
//获取长度,遍历数据结点
int GetLength(PLStack ps)
{
assert(ps != NULL);
int count = 0;
for (LStack* p = ps->next; p != NULL; p = p->next)
{
count++;
}
return count;
}
销毁
//销毁
// 把所有节点清空
void Destroy(PLStack ps)
{
assert(ps!=NULL);
if (ps == NULL)
{
return;
}
PLStack p;
while (ps->next!=NULL)
{
p = ps->next;
ps->next = p->next;
free(p);
}
}
清空
//清空:删除结点的数据及结点本身,只删数据会出现内存泄漏
void ClearStack(PLStack ps)
{
Destroy(ps);
}
完整操作
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int ElemType;
typedef struct LStack
{
ElemType data;//数据
struct LStack* next;//后继
}LStack, * PLStack;
//初始化
void InitStack(PLStack ps)
{
assert(ps->next != NULL);
ps->next = NULL;
}
//入栈,把val的值插入到栈内
bool Push(PLStack ps, ElemType val)
{ //动态创建
LStack* p = (LStack*)malloc(sizeof(LStack));
assert(p != NULL);
p->data = val;
//把p头插到ps
p->next = ps->next;
ps->next = p;
return true;
}
//判空
bool IsEmpty(PLStack ps)
{
return ps->next == NULL;
}
//获取栈顶元素不删除
bool GetTop(PLStack ps, ElemType* rtval)
{
assert(ps != NULL);
if (IsEmpty(ps))
return false;
*rtval = ps->next->data;//栈顶在头部
return true;
}
//获取栈顶元素,且删除栈顶元素
bool Pop(PLStack ps, ElemType* rtval)
{
assert(ps != NULL);
if (IsEmpty(ps))
return false;
LStack* p = ps->next;
*rtval = p->data;//栈顶在头部
//删除p
ps->next = p->next;
free(p);
return true;
}
//获取长度,遍历数据结点
int GetLength(PLStack ps)
{
assert(ps != NULL);
int count = 0;
for (LStack* p = ps->next; p != NULL; p = p->next)
{
count++;
}
return count;
}
//输出
void Show(PLStack ps)
{
assert(ps != NULL);
for (LStack* p = ps->next; p != NULL; p = p->next)
{
printf("%d", p->data);
}
printf("\n");
}
//销毁
// 把所有节点清空
void Destroy(PLStack ps)
{
assert(ps!=NULL);
if (ps == NULL)
{
return;
}
PLStack p;
while (ps->next!=NULL)
{
p = ps->next;
ps->next = p->next;
free(p);
}
}
//清空:删除结点的数据及结点本身,只删数据会出现内存泄漏
void ClearStack(PLStack ps)
{
Destroy(ps);
}
int main()
{
LStack s;
InitStack(&s);
//测试插入
for (int i = 0; i < 10; i++)
{
Push(&s, i);
}
Show(&s);
//测试获取长度函数
int len = GetLength(&s);
printf("%d\n", len);
//测试出栈
ElemType val;
Pop(&s, &val);
printf("val=%d\n", val);
Show(&s);
return 0;
}
测试结果