栈 C底层实现
前言
在初学数据结构的过程中,很有必要不借助STL库函数来实现栈的内部结构,这更方便我们打好栈的基础。下面的程序均使用C实现,更加适合数据结构的初学者。
一.顺序栈
#include <stdio.h>
#include <stdlib.h>
#define true 1
#define false 0
#define MAX 50
typedef int bool;
typedef int ElemType;
typedef struct Stack {
ElemType data[MAX];
int top;
}Stack, *pStack;
//初始化
void InitStack(pStack S);
//入栈
bool Push(pStack S, ElemType e);
//出栈
bool Pop(pStack S, ElemType *e);
//求栈顶元素
bool GetTop(Stack S, ElemType *e);
//栈的长度
int Length(Stack S);
//初始化
void InitStack(pStack S) {
S->top = -1;
}
//入栈
bool Push(pStack S, ElemType e) {
if (S->top == MAX)
return false;
S->top++;
S->data[S->top] = e;
return true;
}
//出栈
bool Pop(pStack S, ElemType *e) {
if (S->top == -1)
return false;
*e = S->data[S->top--];
return true;
}
//求栈顶元素
bool GetTop(Stack S, ElemType *e) {
if (Length(S) == 0)
return false;
return S.data[S.top];
}
//栈的长度
int Length(Stack S) {
return S.top + 1;
}
int main()
{
Stack S;
ElemType e;
InitStack(&S);
Push(&S, 1);
Push(&S, 2);
Push(&S, 3);
Pop(&S, &e);
return 0;
}
二.链栈
有的书上面写着链栈是没有头结点的(或者说头结点就是指向第一个节点),这里为了处理方便,我们将
都定义一个头结点便于操作。
#include <stdlib.h>
#include <stdio.h>
#define false 0
#define true 1
typedef int bool;
typedef char ElemType;
typedef struct Node
{
ElemType data;
struct Node *next;
}Node, *LinkStack;
//链栈初始化
void StackInit(LinkStack *head, LinkStack *top);
//入栈
void Push(LinkStack *top, ElemType e);
//得到栈顶元素
bool GetTop(LinkStack head, LinkStack top, ElemType *e);
//判断栈是否为空
bool Empty(LinkStack head, LinkStack top);
//出栈
bool Pop(LinkStack head, LinkStack *top, ElemType *e);
//栈的长度
int Length(LinkStack head);
//链栈初始化
void StackInit(LinkStack *head, LinkStack *top) {
(*head) = (LinkStack)malloc(sizeof(Node));
(*head)->next = NULL;
(*head)->data = '-1';
*top = (*head);
}
//入栈,注意链栈不需要考虑栈满的情况
void Push(LinkStack *top, ElemType e) {
LinkStack pNew = (LinkStack)malloc(sizeof(Node));
pNew->next = NULL;
pNew->data = e;
pNew->next = (*top)->next;
(*top)->next = pNew;
(*top) = pNew;
}
//判断栈是否为空
bool Empty(LinkStack head, LinkStack top) {
if (head == top)
return true;
else
return false;
}
//得到栈顶元素
bool GetTop(LinkStack head, LinkStack top, ElemType *e) {
if (Empty(head, top))
return false;
*e = top->data;
return true;
}
//栈的长度
int Length(LinkStack head) {
LinkStack p = head->next;
int cnt = 0;
while (p) p = p->next, cnt++;
return cnt;
}
//出栈,注意链栈的出栈并不只是简单的将指针的指向后移,而是要free掉top指向的节点,另外,链栈的指针也不能后移
/*
free操作是释放指针指向的空间,
注意 LinkStack temp = *top 的写法可以写成
Node * temp, temp = *top;
*/
bool Pop(LinkStack head, LinkStack *top, ElemType *e) {
if (Empty(head, *top))
return false;
*e = (*top)->data;
LinkStack temp = *top;
//指针p指向top的前一个指针
LinkStack p = head;
while (p->next->next) p = p->next;
p->next = NULL;
*top = p;
free(temp);//temp是指向Node的指针
return true;
}
int main()
{
//这里的top指针可以类比链表中的Tail指针
LinkStack head = NULL, top = NULL;
StackInit(&head, &top);
Push(&top, '1');
Push(&top, '2');
Push(&top, '3');
ElemType e = '0';//注意之前想让 e = '-1',这样的方式是不被允许的,因为'-1'在这里属于一个字符串
GetTop(head, top, &e);
printf("Top->data = %c\n", e);
printf("栈是否为空?:%d\n长度为%d\n", Empty(head, top), Length(head));
Pop(head, &top, &e);
GetTop(head, top, &e);
printf("Top->data = %c\n", e);
printf("栈是否为空?:%d\n长度为%d\n", Empty(head, top), Length(head));
return 0;
}