栈的定义
首先栈是一种线性表,他比较特殊,只能在表尾进行插入和删除操作。
栈的抽象数据类型
数据类型:
栈的每一个元素依然是结构体,有数据域,有栈顶指针。
对应操作:
1 初始化操作,建立一个空栈。
2 释放栈的分配空间
3 在栈顶插入新的元素
4 删除掉栈顶的元素
5 返回栈的元素个数
栈的顺序存储结构
根据栈的抽象数据类型,现在一一实现它。
先是数据类型:
typedefint SElemType;
typedef struct
{
SElemType data[SIZE];
int top;
}SQStack;
top记录的是数组data中最后面有值的元素的下标。就是栈顶指针的意思啦。
然后是进栈
1 判断是否栈满,即 top 的值是否为 (size-1),若栈满,则返回ERROR。
2 top 自增,成为下一个元素空间的下标。
3 把新的值赋给这个元素空间,然后返回操作成功标志。
代码如下:
Status push(SQStack *Stack, SElemType data)
{
if(Stack->top == (SIZE - 1))
return ERROR;
Stack->top ++;
Stack->data[Stack->top] = data;
return OK;
}
还需要出栈
1 判断栈是不是出空了,即top是否小于0.
2 把要删除的元素赋给返回指针delete_data。
3 top自减。返回操作成功标志。
代码如下:
Status pop(SQStack *Stack, SElemType *delete_data)
{
if(Stack->top < 0)
return ERROR;
*delete_data = Stack->data[Stack->top];
Stack->top--;
return OK;
}
两栈共享空间
主要是为了最大限度利用开辟的存储空间,由于是在一个数组空间内,故两个栈的数据类型必须相同。
定义数据类型
1 开辟数组空间
2 定义整型变量 top1 和 top2
代码如下:
typedef struct
{
SElemType data[SIZE];
int top1;
int top2;
}SQDoubleStack;
其中 SQDoubleStack 可以用来定义结构体类型的变量。
入栈
对于共享空间的栈入栈需要注意:
1 判断栈满,top1 + 1 == top2。
2 判断是入哪个栈。
代码如下:
Status DoubleStack_push(SQDoubleStack *stack, SElemType data, int stack_number)
{
if((stack->top1 + 1) == stack->top2)
return ERROR;
if(stack_number == 1)
{
stack->top1++;
stack->data[stack->top1] = data;
}
else if(stack_number == 2)
{
stack->top2--;
stack->data[stack->top2] = data;
}
return OK;
}
出栈
1 判断需要操作哪个栈
2 top1或者top2移动后,需要判断是否溢出
代码如下:
Status DoubleStack_pop(SQDoubleStack *stack, SElemType* delete_data, int stack_number)
{
if(stack_number == 1)
{
if(--stack->top1 < 0)
{
stack->top1 = 0;
return ERROR;
}
*delete_data = stack->data[stack->top1];
}
else if(stack_number == 2)
{
if(++stack->top2 >= SIZE)
{
stack->top2 = SIZE-1;
return ERROR;
}
*delete_data = stack->data[stack->top2];
}
return OK;
}
栈的链式存储结构
栈顶放在链表的头部,栈底放在尾部。栈顶指针指向第一个结点。
定义链栈的结构代码:
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
入栈
可以根据前面的单链表插入新值的操作猜测下入栈操作:
1 需要新开辟一个结点
2 新结点的next指向top指针所指的结点(原来的第一个结点,即原来的栈顶)
3 top指向新的结点,count++
代码如下:
Status push_linkstack(LinkStack *TOP, SElemType new_data)
{
LinkStackPtr new_node;
new_node = (LinkStackPtr)malloc(sizeof(StackNode));
new_node->data = new_data;
new_node->next = TOP->top;
TOP->top = new_node;
TOP->count++;
return OK;
}
出栈
同样,我们也来回顾下之前的链表删除操作,以此推出出栈:
1 *delete_data = TOP->top->data,栈顶的数据幅值给形参指针
2 delete_node = TOP->top;
3 TOP->top = TOP->top->next。栈顶元素后一个结点的地址给top指针
4 释放delete_node
5 TOP->count–
代码如下:
Status pop_linkstack(LinkStack *TOP, SElemType *delete_data)
{
LinkStackPtr delete_node;
if(TOP->top == NULL)
return ERROR;
*delete_data = TOP->top->data;
delete_node = TOP->top;
TOP->top = TOP->top->next;
free(delete_node);
TOP->count--;
return OK;
}