(二)堆栈(先入后出,后入先出)
1.堆栈的顺序存储
- 定义(Top 是数组下标,对应栈顶元素,Data 用于指向之后定义的数组) - 1 
 2
 3
 4
 5
 6
 7
 8
 9- typedef int Position; 
 typedef struct SNode * PtrToSNode;
 struct SNode
 {
 ElementType * Data;
 Position Top;
 int MaxSize;
 };
 typedef PtrToSNode Stack;
- 生成堆栈 - 1 
 2
 3
 4
 5
 6
 7
 8
 9- /*创建堆栈,其中有一个指针,指向动态分配的数组*/ 
 Stack CreateStack(int MaxSize)
 {
 Stack S = (Stack)malloc(sizeof(struct SNode));
 S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
 S->Top = -1;
 S->MaxSize = MaxSize;
 return S;
 }
- 判断堆栈是否已满 - 1 
 2
 3
 4
 5- bool IsFull(Stack S) 
 {
 /*S->Top 是数组下标,例如数组a有5个元素,最后一个元素下标是5-1,所以是MaxSize-1*/
 return (S->Top==S->MaxSize-1);
 }
- 压栈 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- bool Push(Stack S, ElementType X) 
 {
 if(IsFull(S))
 {
 printf("堆栈已满\n");
 return false;
 }
 else
 {
 /*S->Data[S->Top] 指向末尾元素,下面对最后一个的下一个元素赋值,此时 S->Data[S->Top] 又指向新的末尾元素*/
 S->Data[++(S->Top)] = X;
 return true;
 }
 }
- 判断堆栈是否为空 - 1 
 2
 3
 4- bool IsEmpty(Stack S) 
 {
 return (S->Top==-1);
 }
- 出栈 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- ElementType Pop(Stack S) 
 {
 if(IsEmpty)
 {
 printf("堆栈为空\n");
 return ERROR;
 }
 else
 {
 return S->Data[(S->Top)--];
 }
 }
- 总结:顺序栈就是在数组末尾进行添加和删除操作。 - 2.双栈顶的顺序栈
- 定义 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- typedef int Position; 
 typedef struct SNode * PtrToSNode;
 struct SNode
 {
 ElementType * Data;
 Position Top1;
 Position Top2;
 int MaxSize;
 };
 typedef PtrToSNode Stack;
- 创建堆栈(Top1 和 Top2 都在数组之外) - 1 
 2
 3
 4
 5
 6
 7
 8- Stack CreateStack(int MaxSize) 
 {
 Stack S = (Stack)malloc(sizeof(struct SNode));
 S->Data = (ElementType *)malloc(MaxSize*sizeof(ElementType));
 S->Top1 = -1;
 S->Top2 = MaxSize;
 return S;
 }
- 判断堆栈是否已满(当 Top1 和 Top2 连起来的时候就是满了) - 1 
 2
 3
 4- bool IsFull(Stack S) 
 {
 return (S->Top1+1==S->Top2);
 }
- 压栈(根据 Tag 判断加在左边还是右边) - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- bool Push(Stack S, ElementType X, int Tag) 
 {
 if(IsFull(S))
 {
 printf("堆栈已满\n");
 return false;
 }
 else
 {
 if(Tag==1)
 S->Data[++(S->Top1)] = X;
 else
 S->Data[--(S->Top2)] = X;
 return true;
 }
 }
- 出栈(先根据 Tag 判断那边出栈,再判断那边是否为空) - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23- ElementType Pop(Stack S, int Tag) 
 {
 if(Tag==1)
 {
 if(S->Top1==-1)
 {
 printf("左堆栈为空\n");
 return ERROR;
 }
 else
 return S->Data[(S->Top1)--]
 }
 else
 {
 if(S->Top2==S->MaxSize)
 {
 printf("右堆栈为空\n");
 return ERROR;
 }
 else
 return S->Data[(S->Top2)++];
 }
 }
- 总结:双栈顶和单栈顶操作相似,都是在栈顶添加和删除元素。 - 3.堆栈的链式存储
- 定义 - 1 
 2
 3
 4
 5
 6
 7- typedef struct SNode * PtrToSNode; 
 struct SNode
 {
 ElementType Data;
 PtrToSNode Next;
 };
 typedef PtrToSNode Stack;
- 创建头结点 - 1 
 2
 3
 4
 5
 6
 7
 8- Stack CreateStack() 
 {
 /*创建堆栈头结点,返回该结点指针*/
 Stack S;
 S = (Stack)malloc(sizeof(struct SNode));
 S->Next = NULL;
 return S;
 }
- 入栈(添加在头结点之后) - 1 
 2
 3
 4
 5
 6
 7
 8
 9- bool Push(Stack S, ElementType X) 
 {
 PtrToSNode temp;
 temp = (PtrToSNode)malloc(sizeof(struct SNode));
 temp->Data = X;
 temp->Next = S->Next;
 S->Next = temp;
 return true;
 }
- 判断堆栈是否为空 - 1 
 2
 3
 4- bool IsEmpty(Stack S) 
 {
 return (S->Next==NULL);
 }
- 出栈(删除头结点,返回栈顶元素) - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- ElementType Pop(Stack S) 
 {
 PtrToSNode temp;
 ElementType top;
 if(IsEmpty(S))
 {
 printf("堆栈为空\n");
 return ERROR;
 }
 temp = S->Next;
 top = temp->Data;
 S->Next = temp->Next;
 free(temp);
 return top;
 }
- 总结:用链表实现堆栈,入栈就是在头结点之后添加一个结点,出栈就是释放头结点指向的结点,并返回该结点的数据。头结点那头是栈顶,如果用末尾作为头结点不好。(注意:链表实现跟数组实现的栈顶是位置不一样的)