【数据结构-栈】栈的基本操作
目录
1 顺序表实现栈
两种实现方式:
- 栈顶指针 top 指向栈顶元素
- 栈顶指针 top 指向栈顶元素的下一位置
1.1 定义
# define NUM 50 // 栈的容量
typedef struct Stack{
int data[NUM];
int top;
} Stack;
1.2 初始化
- 栈顶指针 top 指向栈顶元素:
void InitStack (Stack &S){
S.top = -1;
}
- 栈顶指针 top 指向栈顶元素的下一位置:
void InitStack (Stack &S){
S.top = 0;
}
1.3 栈空判断
- 栈顶指针 top 指向栈顶元素:
bool EmptyStack (Stack &S){
if (S.top == -1)
return true;
else
return false;
}
- 栈顶指针 top 指向栈顶元素的下一位置:
bool EmptyStack (Stack &S){
if (S.top == 0)
return true;
else
return false;
}
1.4 栈满判断
- 栈顶指针 top 指向栈顶元素:
bool FullStack (Stack &S){
if (S.top == NUM-1)
return true;
else
return false;
}
- 栈顶指针 top 指向栈顶元素的下一位置:
bool FullStack (Stack &S){
if (S.top == NUM)
return true;
else
return false;
}
1.5 出栈
- 栈顶指针 top 指向栈顶元素:
bool PopStack (Stack &S, int &x){
if (S.top == -1)
return false;
x = S.data[S.top];
S.top--;
return true;
}
- 栈顶指针 top 指向栈顶元素的下一位置:
bool PopStack (Stack &S, int &x){
if (S.top == 0)
return false;
x = S.data[S.top];
S.top--;
return true;
}
1.6 入栈
- 栈顶指针 top 指向栈顶元素:
bool PushStack (Stack &S, const int x){
if (S.top == NUM-1)
return false;
S.top++;
S.data[S.top] = x;
return true;
}
- 栈顶指针 top 指向栈顶元素的下一位置:
bool PushStack (Stack &S, const int x){
if (S.top == NUM)
return false;
S.top++;
S.data[S.top] = x;
return true;
}
1.7 读栈顶元素
- 栈顶指针 top 指向栈顶元素:
bool GetStackTop (Stack &S, int &x){
if (S.top == -1)
return false;
x = S.data[S.top];
return true;
}
- 栈顶指针 top 指向栈顶元素的下一位置:
bool GetStackTop (Stack &S, int &x){
if (S.top == 0)
return false;
x = S.data[S.top-1];
return true;
}
2 单向链表实现栈
实现方法:
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置(相当于带头结点的链表,头结点正好可以用来记录当前栈存储元素的个数)
【注】“栈顶元素在链表表尾”较难实现,因为单向链表只有后继结点。
2.1 定义
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
#define NUM 50 // 栈的容量
typedef struct LinkNode{
int data;
struct LinkNode *next;
} LinkNode, *LinkStack;
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
#define NUM 50 // 栈的容量
typedef struct LinkNode{
int data;
struct LinkNode *next;
} LinkNode, *LinkStack;
int count; // 记录栈内当前元素个数
2.2 初始化
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
bool InitStack (LinkStack &top){
top = NULL;
count = 0;
return true;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
bool InitStack (LinkStack &head){
head = (LinkNode *) malloc(sizeof(LinkNode));
if (head == NULL)
return false;
head->data = 0; // 用来记录当前栈存储元素的个数
head->next = NULL; // 后继结点为空
return true;
}
2.3 栈空判断
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
void EmptyStack (LinkStack &top){
if (top == NULL)
return true;
return false;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
void EmptyStack (LinkStack &head){
if (head->data == 0)
return true;
return false;
}
2.4 栈满判断
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:需要借助外部变量 count 实现
void FullStack (LinkStack &head){
if (count == NUM)
return true;
return false;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
void FullStack (LinkStack &head){
if (head->data == NUM)
return true;
return false;
}
2.5 出栈
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
bool PopStack (LinkStack &top, int &x){
LinkNode *topNext; // 记录栈顶结点(表头结点)的下一个结点
if (top == NULL)
return false;
x = top->data;
topNext = top->next; // 记录栈顶结点(表头结点)的下一个结点
free(top);
count--; // 栈内元素个数减少
return true;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
bool PopStack (LinkStack &head, int &x){
LinkNode *top; // 记录表头结点的下一个结点(即栈顶结点)
LinkNode *topNext; // 记录栈顶结点的下一个结点
if (head->data == 0)
return false;
top = head->next; // 记录表头结点的下一个结点(即栈顶结点)
topNext = top->next; // 记录栈顶结点的下一个结点
x = top->data;
free(top);
head->data--; // 栈内元素个数减少
head->next = topNext;
return true;
}
2.6 入栈
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
bool PushStack (LinkStack &top, const int x){
LinkNode *newTop; // 新结点
newTop = (LinkNode *) malloc(sizeof(LinkNode));
newTop->data = x;
newTop->next = top; // 新结点的后继结点指向当前栈顶结点
count++; // 栈内元素增加
top = newTop; // 新结点作为新的栈顶结点
return true;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
bool PushStack (LinkStack &head, const int x){
LinkNode *top; // 记录表头结点的下一个结点(即栈顶结点)
LinkNode *newTop; // 新结点
if (head->data == NUM)
return false;
top = head->next; // 记录表头结点的下一个结点(即栈顶结点)
topNext = top->next; // 记录栈顶结点的下一个结点
newTop = (LinkNode *) malloc(sizeof(LinkNode));
newTop->data = x;
newTop->next = top; // 新结点的下一个结点为当前栈顶结点
head->data++; // 栈内元素个数增加
head->next = newTop; // 新结点作为表头结点的后继结点
return true;
}
2.7 读栈顶元素
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
bool GetStackTop(LinkStack top, int &x){
if (top == NULL)
return false;
x = top->data;
return true;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
bool GetStackTop(LinkStack head, int &x){
LinkNode *top = head->next;
if (head->data == 0)
return false;
x = top->data;
return true;
}
3 双向链表实现栈
实现方法:
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素
- 栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置(相当于带头结点的链表,头结点正好可以用来记录当前栈存储元素的个数)
【注】“栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素的下一位置”没有意义。
3.1 定义
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
- 栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素:
typedef struct LinkNode{
int data;
struct LinkNode *prev;
struct LinkNode *next;
} LinkNode, *LinkStack;
int count;
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
typedef struct LinkNode{
int data;
struct LinkNode *prev;
struct LinkNode *next;
} LinkNode, *LinkStack;
3.2 初始化
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
bool InitStack (LinkStack &top){
top = NULL;
count = 0;
return true;
}
- 栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素:
bool InitStack (LinkStack &top){
top = NULL;
count = 0;
return true;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
bool InitStack (LinkStack &head){
head = (LinkNode *) malloc(sizeof(LinkNode));
if (head == NULL)
return false;
head->data = 0; // 用来记录当前栈存储元素的个数
head->prev = NULL; // 前驱结点为空
head->next = NULL; // 后继结点为空
return true;
}
3.3 栈空判断
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
void EmptyStack (LinkStack &top){
if (top == NULL)
return true;
return false;
}
- 栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素:
void EmptyStack (LinkStack &top){
if (top == NULL)
return true;
return false;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
void EmptyStack (LinkStack &head){
if (head->data == 0)
return true;
return false;
}
3.4 栈满判断
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:需要借助外部变量 count 实现
- 栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素:需要借助外部变量 count 实现
void FullStack (LinkStack &head){
if (count == NUM)
return true;
return false;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
void FullStack (LinkStack &head){
if (head->data == NUM)
return true;
return false;
}
3.5 出栈
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
bool PopStack (LinkStack &top, int &x){
LinkNode *topNext; // 记录栈顶结点(表头结点)的下一个结点
if (top == NULL)
return false;
x = top->data;
topNext = top->next; // 记录栈顶结点(表头结点)的下一个结点
free(top);
count--; // 栈内元素个数减少
topNext->prev = NULL;
top = topNext; // 旧栈顶结点(表头结点)的下一个结点成为新的栈顶结点
return true;
}
- 栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素:
bool PopStack (LinkStack &top, int &x){
LinkNode *topPrev; // 记录栈顶结点(表尾结点)的上一个结点
if (top == NULL)
return false;
x = top->data;
topPrev = top->prev; // 记录栈顶结点(表尾结点)的上一个结点
free(top);
count--; // 栈内元素个数减少
topPrev->next = NULL;
top = topNext; // 旧栈顶结点(表尾结点)的上一个结点成为新的栈顶结点
return true;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
bool PopStack (LinkStack &head, int &x){
LinkNode *top; // 记录表头结点的下一个结点(即栈顶结点)
LinkNode *topNext; // 记录栈顶结点的下一个结点
if (head->data == 0)
return false;
top = head->next; // 记录表头结点的下一个结点(即栈顶结点)
topNext = top->next; // 记录栈顶结点的下一个结点
x = top->data;
free(top);
head->data--; // 栈内元素个数减少
head->next = topNext; // 旧栈顶结点(表头结点)的下一个结点成为新的栈顶结点
topNext->prev = head; // 新栈顶结点的上一个结点为头结点
return true;
}
3.6 入栈
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
bool PushStack (LinkStack &top, const int x){
LinkNode *newTop; // 新结点
newTop = (LinkNode *) malloc(sizeof(LinkNode));
newTop->data = x;
newTop->prev = NULL;
newTop->next = top; // 新结点的后继结点指向当前栈顶结点
count++; // 栈内元素个数增加
top->prev = newTop; // 当前栈顶结点的前驱结点为新结点
top = newTop; // 新结点作为新的栈顶结点
return true;
}
- 栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素:
bool PushStack (LinkStack &top, const int x){
LinkNode *newTop; // 新结点
newTop = (LinkNode *) malloc(sizeof(LinkNode));
newTop->data = x;
newTop->prev = top; // 新结点的后继结点指向当前栈顶结点
newTop->next = NULL;
count++; // 栈内元素个数增加
top->next = newTop; //当前栈顶结点的后继结点为新结点
top = newTop; // 新结点作为新的栈顶结点
return true;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
bool PushStack (LinkStack &head, const int x){
LinkNode *top; // 记录表头结点的下一个结点(即栈顶结点)
LinkNode *newTop; // 新结点
if (head->data == NUM)
return false;
top = head->next; // 记录表头结点的下一个结点(即栈顶结点)
newTop = (LinkNode *) malloc(sizeof(LinkNode));
newTop->data = x;
newTop->prev = head; // 新结点的前驱结点为头结点
newTop->next = top; // 新结点的后继结点为当前栈顶结点
head->data++; // 栈内元素个数增加
top->prev = newTop; // 当前栈顶结点的前驱结点指向新结点
head->next = newTop; // 新结点作为表头结点的后继结点
return true;
}
3.7 读栈顶元素
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素:
bool GetStackTop(LinkStack top, int &x){
if (top == NULL)
return false;
x = top->data;
return true;
}
- 栈顶元素在链表表尾,且栈顶指针 top 指向栈顶元素:
bool GetStackTop(LinkStack top, int &x){
if (top == NULL)
return false;
x = top->data;
return true;
}
- 栈顶元素在链表表头,且栈顶指针 top 指向栈顶元素的下一位置:
bool GetStackTop(LinkStack head, int &x){
LinkNode *top = head->next;
if (head->data == 0)
return false;
x = top->data;
return true;
}