1.栈的详解及实现
1.1
栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。
进行数据插入和删除操作的一端
称为栈顶,另一端称为栈底。
栈中的数据元素遵守后进先出
LIFO
(
Last In First Out
)的原则。
压栈:栈的插入操作叫做进栈
/
压栈
/
入栈,
入数据在栈顶
。
出栈:栈的删除操作叫做出栈。
出数据也在栈顶
。
LIFO原则图解:
![](https://i-blog.csdnimg.cn/blog_migrate/a3e59ef2b0ce7cb3a1f7c405b71298c1.png)
1.2
栈的实现
栈的实现一般可以使用
数组或者链表实现
,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
数组栈的实现通常选取尾部作为入栈、出栈的位置,其实就是实现尾插和尾删的操作。不是说头部的头插和头删就不行,只是数组的结构决定了要进行头删和头插需要挪动元素,没必要那么麻烦。
1.3数组栈结构的定义
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
capacity记录容量的大小、top确定元素数量的大小,同时将top初始化为0,使top指向栈顶元素的下一个(还可以初始化为-1,即使top指向栈顶元素)。
1.4数组栈的初始化
void STInit(ST* psl)
{
assert(psl);
psl->a = NULL;
psl->top = 0;
psl->capacity = 0;
}
1.5入栈
void STPush(ST* psl, STDataType x)
{
assert(psl);
if (psl->top == psl->capacity)
{
int newcapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
STDataType* tmp = (STDataType*)realloc(psl->a,sizeof(STDataType)*newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
psl->a = tmp;
psl->capacity = newcapacity;
}
psl->a[psl->top] = x;
psl->top++;
}
将top初始化为0,其实使得扩容时top和capacity进行比较变得更加容易理解和方便。剩余的操作其实还是在顺序表的基础之上,挺容易理解的。
1.6出栈
void STPop(ST* psl)
{
assert(psl);
assert(!STEmpty(psl));//判空
psl->top--;
}
这里要注意的是出栈的时候,如果栈为空就不用出栈,所以断言一下。
判空代码:
bool STEmpty(ST* psl)
{
assert(psl);
return psl->top == 0;
}
1.7返回栈顶元素
STDataType STTop(ST* psl)
{
assert(psl);
assert(!STEmpty(psl));
return psl->a[psl->top-1];
}
返回栈顶元素同样需要判空。
1.8返回栈中元素数量
int STSize(ST* psl)
{
assert(psl);
return psl->top;
}
当然链式栈也可以实现,为了遵循后进先出的原则可以将表头作为栈顶,出栈和入栈就对应头删和头插,不使用尾插和尾删是因为需要找尾巴,遍历链表引起不必要的浪费。
直接上代码:
void STDestory(ST* psl)
{
ST* cur = psl;
while (cur)
{
ST* next = cur->next;
free(cur);
cur = next;
}
cur = NULL;
}
void STPush(ST** psl, STDataType x)
{
assert(psl);
ST* newnode = (ST*)malloc(sizeof(ST));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->data = x;
newnode->next = *psl;
*psl = newnode;
}
void STPop(ST** psl)
{
assert(psl);
assert(*psl);
ST* del = *psl;
*psl = ( * psl)->next;
free(del);
}
STDataType STTop(ST* psl)
{
assert(psl);
assert(!STEmpty(psl));
return psl->data;
}//返回栈顶元素
bool STEmpty(ST* psl)
{
return psl == NULL;
}//判空
int STSize(ST* psl)
{
int count = 0;
ST* cur = psl;
while (cur)
{
cur = cur->next;
count++;
}
return count;
}//返回栈中元素数量
void STPrintf(ST* psl)
{
printf("%d ",STTop(psl));
}
许多操作其实大同小异,重要的是理解栈的原理。最后接口函数的测试和出现问题的调试也非常重要。
今天的分享就到这里,希望大家一起提高!!!