栈的定义:
栈是限定在表尾进行插入和删除的线性表。
我们把允许插入和删除的一端称为栈顶,另一端称为栈底,没有任何元素的栈称为空栈。
栈的特性:
1.它是一个线性表。
2.它限定了处理元素的位置只能在栈顶。
栈的图解:
栈的顺序存储结构实现:(数组栈)
typedef struct {
int data[MAXSIZE]; //存储元素的数组
int top; //栈顶指针
}sqstack;
MAXSIZE代表最大个数,在主函数前面有宏定义。
#define MAXSIZE 10
1.栈的初始化:
/*主函数部分为
sqstack *s = Initstack();
*/
sqstack* Initstack() {
sqstack *s = (sqstack*)malloc(sizeof(sqstack)); //s为栈指针
s -> top = -1; //栈顶位置
return s; //返回此时创建的指针
}
最开始的时候我们把栈顶指针设置在 -1 处,方便后续判断。
2.入栈操作:
bool Push(sqstack *s, int n) {
if (s->top == MAXSIZE - 1) { //先判断是否栈满
return false;
}
s->top++; //栈顶指针+1
s->data[s->top] = n; //将传入的值赋值给栈顶空间
return true;
}
要特别注意的两点内容:
1)传入的栈指针必须是已经创建好的指针,所指向的内存空间是已经前面申请过的。
2)一定记着先要判断。
3.出栈操作:
bool Pop(sqstack *s, int *m) {
if (s->top == -1) { //首先判断是否栈空
return false;
}
*m = s->data[s->top]; //将要删除的元素赋值给*m
s->top--; //栈顶指针-1
return true;
}
此时传入的栈指针也必须是经过处理的。
栈的链式存储:(链栈)
typedef struct stacknode {
int data; //存放栈的数据
struct stacknode *next; //下一个指针
}stacknode, *Linkstackptr;
typedef struct Linkstack {
Linkstackptr top; //top栈顶指针
int count; //栈元素计数器
};
链栈的绝大部分操作和单链表相似,只是push和pop稍微不同。
用top指针代替头结点进行操作,类似的将栈顶放在链表头部进行操作。
1.进栈操作:
Status Push(Linkstack *s, int e) {
Linkstackptr p = (Linkstackptr )malloc(sizeof(stacknode));
p->data = e;
p->next = s->top; //首先建立新元素与原栈之间的联系(1)
s->top = p; //再更新栈顶指针的位置(2)
s->count++;
return OK;
}
有图有真相:(自己创建和传入的参数可自己命名)
2.出栈操作:
Status Pop(Linkstack *s, int *e) {
Linkstackptr p;
if (stackempty(*s) == NULL) { //先判断栈是否为空
return ERROR;
}
*e = s->top->data; //用e返回要pop的值
p = s->top; //用指针变量存储栈顶元素 (3)
s->top = s->top->next; //使栈顶指针向后移动 (4)
free(p); //释放栈顶元素
s->count--;
return OK;
}
在来张图理解一下吧: