目录
1. 什么是栈
栈(Stack)是一种常见的数据结构,它遵循"先进后出"(Last In First Out,简称LIFO)的原则。在栈中,最后一个添加的元素是第一个被移除的,类似于我们平时堆叠的盘子,只能从最上面取下或放上。
示意图:
2. 顺序栈的实现
2.1 定义顺序栈结构
#define MaxSize 50
typedef struct{
int data[MaxSize];
int top; //栈顶元素的下标
}sqStack;
2.2 初始化
void InitStack(sqStack &s) {
s.top = -1; //-1表示栈空
}
2.3 判空
bool StackEmpty(sqStack s) {
if (s.top == -1)
return true;
else
return false;
}
2.4 进栈
bool Push(sqStack& s,int elem) {
if (s.top == MaxSize - 1)//栈满
return false;
s.data[++s.top] = elem;
return true;
}
2.5 出栈
bool Pop(sqStack &s,int &elem) {
if (s.top == -1) //栈空
return false;
elem = s.data[s.top--];
return true;
}
2.6 获取栈顶元素
bool GetTop(sqStack s, int &elem) {
if (s.top == -1) //栈空
return false;
elem = s.data[s.top];
return true;
}
3. 链栈的实现
3.1 定义链栈结点结构
typedef struct LinkNode{
int data;
LinkNode* next;
}*LinkStack;
3.2 初始化
void InitStack(LinkStack& LiStack) {
LiStack=NULL;
}
3.3 判空
bool EmptyStack(LinkStack LiStack) {
if (LiStack == NULL)
return true;
return false;
}
3.4 入栈
void Push(LinkStack &head, int elem) {
LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = elem;
s->next = head;
head = s;
}
3.5 出栈
void Pop(LinkStack& LiStack, int& elem) {
if (EmptyStack(LiStack)) {
cout << "栈空" << endl;
return;
}
elem = LiStack->data;
LinkNode* p = LiStack;
LiStack = LiStack->next;
free(p);
}
3.6 获取栈顶元素
bool GetTop(LinkStack LiStack,int &x) {
if (EmptyStack(LiStack)) {
cout << "栈空" << endl;
return false;
}
x = LiStack->data;
return true;
}
4. 顺序栈与链栈的比较
4.1 空间复杂度
- 顺序栈的空间复杂度为O(n),需要预先分配固定大小的数组空间。
- 链栈的空间复杂度为O(n),每个元素需要一个结点和指针来连接。
4.2 时间复杂度
- 顺序栈和链栈的入栈和出栈操作时间复杂度都为O(1),即常数时间。
- 链栈的插入和删除元素操作更快,而顺序栈的查找元素操作更快。
4.3 动态性
- 顺序栈的大小固定,无法动态扩展,当栈满时无法继续入栈。
- 链栈可以动态地申请和释放内存空间,不受固定大小的限制。
5. 总结
栈是一种重要的数据结构,在计算机科学和编程中广泛应用。本文介绍了栈的基本概念和特点,并分别实现了顺序栈和链栈的相关操作,包括初始化、入栈、出栈和获取栈顶元素。通过比较顺序栈和链栈的特点,我们可以根据实际需求选择合适的栈实现。顺序栈适用于空间固定、操作频繁的场景,而链栈适用于动态扩展、灵活性较高的场景。
【结语】:希望本文对读者理解栈的实现和应用有所帮助。栈在计算机科学中有着重要的地位,掌握栈的原理和使用方法,对于编写高效、优雅的代码有着重要意义。如有疑问或意见,欢迎留言讨论。感谢阅读!