这次的数据结构是一种特殊的线性表:栈(Stack)
栈的特点是后入先出(LIFO),可见的只有栈顶的一个元素。
栈在程序中的地位非常重要,其中最重要的应用就是函数的调用。每次函数调用时都会创建该函数的一个“活动记录”( Activation Record ,或称作“帧”( Frame ))压入运行时堆栈中,用于保存函数的参数,返回值,返回指令地址,返回活动记录地址,局部变量等内容。当然,在高级语言中我们不需要手动完成这一工作,学习汇编语言时会体会到其真正过程。
下面给出笔者对于堆栈的两种实现。首先是顺序(数组)存储实现:
// Stack.h
#include <stdio.h>
#include <stdlib.h>
struct StackRecord;
typedef struct StackRecord *Stack;
int IsEmpty(Stack S);
int IsFull(Stack S);
Stack CreateStack(int MaxElements);
void DisposeStack(Stack S);
void MakeEmpty(Stack S);
void Push(ElementType X, Stack S);
ElementType Top(Stack S);
void Pop(Stack S);
ElementType TopAndPop(Stack S);
// Stack.c
#include "Stack.h"
struct StackRecord{
int Capacity;
int TopOfStack;
ElementType *Array;
};
int IsEmpty(Stack S)
{
return S->TopOfStack == -1;
}
int IsFull(Stack S)
{
return S->TopOfStack == S->Capacity - 1;
}
Stack CreateStack(int MaxElements)
{
Stack ret;
if((ret = (Stack)malloc(sizeof(struct StackRecord))) != NULL)
{
ret->TopOfStack = -1;
ret->Capacity = MaxElements;
if((ret->Array = (ElementType*)malloc(MaxElements * sizeof(ElementType))) != NULL)
return ret;
free(ret);
}
printf("Error! Out of memory! \n");
return NULL;
}
void DisposeStack(Stack S)
{
if(S)
{
free(S->Array);
free(S);
}
}
void MakeEmpty(Stack S)
{
S->TopOfStack = -1;
}
void Push(ElementType X, Stack S)
{
if(IsFull(S))
{
printf("Error! The stack is full! \n");
return;
}
(S->Array)[++(S->TopOfStack)] = X;
}
ElementType Top(Stack S)
{
if(IsEmpty(S))
{
printf("Error! The stack is empty! \n");
return 0;
}
return (S->Array)[(S->TopOfStack)];
}
void Pop(Stack S)
{
if(IsEmpty(S))
{
printf("Error! The stack is empty! \n");
return;
}
S->TopOfStack -= 1;
}
ElementType TopAndPop(Stack S)
{
if(IsEmpty(S))
{
printf("Error! The stack is empty! \n");
return 0;
}
return (S->Array)[(S->TopOfStack)--];
}
接下来是链式存储实现:
// Stack.h
#include <stdio.h>
#include <stdlib.h>
struct _Node;
typedef struct _Node Node;
typedef Node *PtrToNode;
typedef PtrToNode Stack;
int IsEmpty(Stack S);
Stack CreateStack();
void DisposeStack(Stack S);
void MakeEmpty(Stack S);
void Push(ElementType X, Stack S);
ElementType Top(Stack S);
void Pop(Stack S);
// Stack.c
#include "Stack.h"
struct _Node
{
ElementType Element;
struct _Node *Next;
};
void print(Stack S)
{
for (PtrToNode p = S->Next; p; p = p->Next)
{
printf("%d ", p->Element);
}
printf("\n");
}
int main()
{
Stack s = CreateStack();
print(s);
Pop(s);
printf("%d", Top(s));
Push(2, s);
Push(3, s);
Push(5, s);
print(s);
Pop(s);
print(s);
MakeEmpty(s);
print(s);
DisposeStack(s);
getchar();
getchar();
}
int IsEmpty(Stack S)
{
return S->Next == NULL;
}
Stack CreateStack()
{
Stack ret;
if ((ret = (Stack)malloc(sizeof(Node))) != NULL)
{
ret->Next = NULL;
return ret;
}
printf("Error! Out of memory! \n");
return 0;
}
void DisposeStack(Stack S)
{
PtrToNode p = S;
while (S != NULL)
{
S = S->Next;
free(p);
p = S;
}
}
void MakeEmpty(Stack S)
{
if (S == NULL)
{
printf("Error! It's not a Stack!\n");
return;
}
while (!IsEmpty(S))
Pop(S);
}
void Push(ElementType X, Stack S)
{
PtrToNode t;
if ((t = (PtrToNode)malloc(sizeof(Node))) != NULL)
{
t->Element = X;
t->Next = S->Next;
S->Next = t;
return;
}
printf("Error! Out of memory! \n");
}
ElementType Top(Stack S)
{
if (S->Next == NULL)
{
printf("Error! The stack is empty! \n");
return 0;
}
return S->Next->Element;
}
void Pop(Stack S)
{
PtrToNode p = S->Next;
if (p == NULL)
{
printf("Error! The stack is empty! \n");
return;
}
S->Next = p->Next;
free(p);
}
以上就是堆栈的两种实现。由于较为简单,不再给出测试样例。