栈是一种先入后出(后入先出)的数据结构,栈的这种性质被用于很多场景,如代码编译、代码语法检查、函数调用等。
栈的实现方式有两种:用链表实现、用数组实现。
一.链表实现
看过几本数据结构的书如《Data Structures and Algorithm Analysis in C》与《C Primer Plus》,也可能是由于写惯了Java代码,总是感觉书中的代码抽象的力度不够,所以自己实现了一下,与他们的实现相比略显拖沓,不过我认为抽象与封装的重要性比简洁性更重要。
以链表的形式实现,Stack持有一个header指针,每次push都将header的next指针指向新创建的节点,所以栈顶节点就是header->next,代码如下:
头文件:
#ifndef _Stack_H
#define _Stack_H
/*
*以链表的方式实现栈
*/
/*栈节点结构体*/
struct NodeStruct;
/*栈结构体*/
struct StackStruct;
/*栈节点结构体存储的元素数据类型*/
typedef int ElementType;
/*栈节点结构体指针*/
typedef struct NodeStruct *PtrToNode;
/*栈结构体指针*/
typedef struct StackStruct *PtrToStack;
/*栈节点*/
typedef PtrToNode Node;
/*栈*/
typedef PtrToStack Stack;
/*初始化一个栈*/
Stack initStack();
/*push元素*/
void push(Stack stack,ElementType element);
/*返回栈顶元素,栈为空时返回NULL*/
Node top(Stack stack);
/*栈顶元素出栈*/
void pop(Stack stack);
/*销毁栈*/
void destoryStack(Stack stack);
/*打印栈结构*/
void printStack(Stack stack);
/**/
struct NodeStruct{
ElementType element;
Node next;
};
/**/
struct StackStruct{
Node header;
int size;
};
#endif
实现文件:
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
Stack initStack(){
Stack stack;
Node header;
header = malloc(sizeof(struct NodeStruct));
header->next = NULL;
stack = malloc(sizeof(struct StackStruct));
stack->header = header;
stack->size = 0;
}
void push(Stack stack,ElementType element){
Node header,topNode,newNode;
header= stack->header;
topNode = header->next;
newNode = malloc(sizeof(struct NodeStruct));
newNode->element = element;
newNode->next = topNode;
header->next = newNode;
stack->size++;
}
Node top(Stack stack){
Node header, topNode;
header = stack->header;
topNode = header->next;
return topNode;
}
void pop(Stack stack){
Node header,topNode;
header = stack->header;
topNode = top(stack);
if(topNode != NULL){
header->next = topNode->next;
stack->size--;
free(topNode);
topNode = NULL;
}
}
void destoryStack(Stack stack){
Node header,topNode,temp;
header = stack->header;
topNode = header->next;
while(topNode != NULL){
temp = topNode->next;
free(topNode);
topNode = temp;
}
free(header);
header = NULL;
free(stack);
stack = NULL;
}
void printStack(Stack stack){
Node header,topNode;
header = stack->header;
topNode = header->next;
printf("[");
while(topNode != NULL){
printf("%d,",topNode->element);
topNode = topNode->next;
}
if(stack->size > 0){
printf("\b]\n");
}else{
printf("]\n");
}
}
以上代码在以下环境中编译并测试通过:
线程模型:posix
gcc 版本 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
二.以数组实现
以数组实现也很简单,我们之需要初始化一个固定大小的数组,并以一个变量topOfStack记录栈顶元素在数组中的下标即可,push元素时需要check一下栈是否满了,当然我们可以实现栈可扩展;pop时需要将topOfStack递减,以保证该值可以从数组中索引某个元素作为栈顶元素。
头文件
#ifndef _Array_Stack
/*声明栈结构体*/
struct StackStruct;
/*定义栈存储元素的类型*/
typedef int ElementType;
/*定义栈结构体指针*/
typedef struct StackStruct *PtrToStack;
/*定义栈*/
typedef PtrToStack Stack;
/*初始化一个栈,capacity为栈初始大小*/
Stack initStack(int capacity);
/*push元素*/
void push(Stack stack,ElementType element);
/*返回栈顶元素*/
ElementType top(Stack stack);
/*栈顶元素出栈*/
ElementType pop(Stack stack);
/*销毁栈*/
void destoryStack(Stack stack);
/*打印栈结构*/
void printStack(Stack stack);
#endif
实现
#include <stdio.h>
#include <stdlib.h>
#include "arraystack.h"
//定义栈默认大小
#define DefaultCapacity ( 100 )
//定义栈结构体
struct StackStruct{
int size;
int capacity;
int topOfStack;
ElementType *array;
};
Stack initStack(int capacity){
Stack stack;
if(capacity > DefaultCapacity)
capacity = DefaultCapacity;
stack = malloc(sizeof(struct StackStruct));
if(stack == NULL){
fprintf(stderr,"%s\n","OutOfMemory!");
exit(1);
}
stack->size = 0;
stack->capacity = capacity;
stack->array = malloc(sizeof(ElementType)*capacity);
stack->topOfStack = -1;
if(stack->array == NULL){
fprintf(stderr,"%s\n","OutOfMemory!");
exit(1);
}
return stack;
}
void push(Stack stack,ElementType element){
//stack is full
if(stack->size == stack->capacity){
return;
}
stack->array[++stack->topOfStack] = element;
stack->size++;
}
ElementType top(Stack stack){
ElementType result;
result = stack->array[stack->topOfStack];
return result;
}
ElementType pop(Stack stack){
ElementType result;
result = top(stack);
stack->topOfStack--;
return result;
}
void destoryStack(Stack stack){
if(stack == NULL)
return;
free(stack->array);
stack->array = NULL;
free(stack);
stack = NULL;
}
void printStack(Stack stack){
if(stack == NULL || stack->size ==0)
return;
int index;
for(index = stack->topOfStack;index >= 0;index--){
printf("|_%d_|\n",stack->array[index]);
}
printf("stack info >>{[capacity:%d],[size:%d],[topOfStack:%d]}\n",
stack->capacity,stack->size,stack->topOfStack);
}