栈是一种后进先出(LIFO)的特殊的线性表。它限定仅在表尾进行插入或删除,表尾端被称作栈顶,表头端称作栈底。不含元素的空表称为空栈。
栈的基本操作有三个,分别为:入栈、出栈。取栈顶元素。
下面,我们先来基于顺序表实现栈,即顺序栈。
seqstack.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
typedef char SeqStackType;
typedef struct SeqStack{
SeqStackType *data;
size_t size;
size_t capacity;
}SeqStack;
void SeqStackInit(SeqStack* stack);//初始化
void SeqStackDestroy(SeqStack* stack);//销毁
void SeqStackPrint(SeqStack* stack,const char* msg);//打印
void SeqStackPush(SeqStack* stack,SeqStackType value);//入栈
void SeqStackPop(SeqStack* stack);//出栈
int GetTop(SeqStack* stack,SeqStackType* value);//取栈顶元素
seqstack.c:
#include "seqstack.h"
void SeqStackPrint(SeqStack* seqstack,const char* msg){
printf("[%s]\n",msg);
size_t i = 0;
for(;i < seqstack->size;i++){
printf("[%c] ",seqstack->data[i]);
}
printf("\n");
}
void SeqStackInit(SeqStack* seqstack){
if(seqstack == NULL){
return;
}
seqstack->size = 0;
seqstack->capacity = 1024;
seqstack->data = (SeqStackType*)malloc(seqstack->capacity * sizeof(SeqStackType));
}
void SeqStackDestroy(SeqStack* seqstack){
if(seqstack == NULL){
return;
}
free(seqstack->data);
seqstack->size = 0;
seqstack->capacity = 0;
}
void SeqStackResize(SeqStack* seqstack){
if(seqstack == NULL){
return;
}
if(seqstack->size < seqstack->capacity){
return;
}
SeqStackType* new_ptr = (SeqStackType*)malloc(seqstack->capacity*sizeof(SeqStackType)*2+1);
size_t i =0;
//搬运原来的数据
for(;i < seqstack->size;i++){
new_ptr[i] = seqstack->data[i];
}
free(seqstack->data);
seqstack->data = new_ptr;
}
void SeqStackPush(SeqStack* seqstack,SeqStackType value){
if(seqstack == NULL){
return;
}
if(seqstack->size >= seqstack->capacity){
SeqStackResize(seqstack);
}
seqstack->data[seqstack->size++] = value;
}
void SeqStackPop(SeqStack* seqstack){
if(seqstack == NULL){
//非法输入
return;
}
if(seqstack->size == 0){
return;
}
--seqstack->size;
return;
}
int GetTop(SeqStack* seqstack,SeqStackType* value){
if(seqstack == NULL || value == 0){
return 0;
}
if(seqstack->size == 0){
return 0;
}
//不能--size,会把size的值修改
*value = seqstack->data[seqstack->size-1];
return 1;
}
test.c:
#include "seqstack.h"
#define PRINT_HEADER printf("\n============%s============\n",__FUNCTION__)
void test(){
PRINT_HEADER;
SeqStack stack;
SeqStackInit(&stack);
printf("size except 0,actual %lu\n",stack.size);
printf("capacity except 1024,except %lu\n",stack.capacity);
SeqStackPrint(&stack,"顺序栈的初始化");
SeqStackPush(&stack,'a');
SeqStackPush(&stack,'b');
SeqStackPush(&stack,'c');
SeqStackPush(&stack,'d');
SeqStackPrint(&stack,"入栈四个元素");
SeqStackPop(&stack);
SeqStackPrint(&stack,"出栈一个元素");
SeqStackPop(&stack);
SeqStackPrint(&stack,"出栈两个元素");
SeqStackPop(&stack);
SeqStackPrint(&stack,"出栈三个元素");
SeqStackPop(&stack);
SeqStackPrint(&stack,"出栈四个元素");
SeqStackPop(&stack);
SeqStackPrint(&stack,"尝试对空栈进行出栈操作");
SeqStackPush(&stack,'a');
SeqStackPush(&stack,'b');
SeqStackPush(&stack,'c');
SeqStackPush(&stack,'d');
SeqStackPrint(&stack,"入栈四个元素");
SeqStackType value;
int ret = GetTop(&stack,&value);
printf("ret expect 1,actual %d\n",ret);
printf("top except d,actual %c\n",value);
SeqStackDestroy(&stack);
SeqStackPrint(&stack,"销毁栈");
}
int main(){
test();
}
由于栈的操作相对较少,所以我们就将测试放到了一起,而并没有分别对每个函数进行测试,这样不仅较少了代码量,也减少了代码的重复性。
结果演示: