栈的特点:后进先出
一、顺序栈
如果在顺序表的头部入栈,则需要将原有站内的元素依次后移,时间复杂度On,
所以可以采用尾部入栈,入栈时只需要把size下标设置为指定元素,出栈时直接删除下标为size-1就行,
stack.h #pragma once #include<stdio.h> typedef char stacktype; typedef struct SeqStack { stacktype* data;//动态申请内存空间 int size;//已有元素 int capacity;//容量 }SeqStack; void Init(SeqStack* stack);//初始化 void Destory(SeqStack* stack);//销毁 void Push(SeqStack* stack,stacktype value);//压栈 void Pop(SeqStack* stack);//出栈 int front(SeqStack* stack,stacktype* value);//提取栈顶元素,value为输出型参数
因为顺序表总体来说还是一个数组的形式,所以存储容量是固定的,因此需要容量达到上限时开辟新的内存空间
stack.c #include<stdio.h> #include"stack.h" #include<stdlib.h> void Init(SeqStack* stack) { if(stack == NULL) { return; } stack->size = 0; stack->capacity = 1000; stack->data = (stacktype*)malloc(sizeof(stacktype)*(stack->capacity));//初始化时先开辟内存空间 return; }
void Destory(SeqStack* stack) { stack->size = 0; stack->capacity = 0; free(stack->data); return; }
void Push(SeqStack* stack,stacktype value) { if(stack == NULL) { return;//非法输入 } if(stack->size >= stack->capacity) //如果达到容量或者超过上限时,开辟新的内存空间 { stack->capacity = stack->capacity*2+1; stacktype* New_data = (stacktype*)malloc (sizeof(stacktype)*(stack->capacity)); int i = 0; for(;i<stack->size;++i) { New_data[i] = stack->data[i]; //将之前内存空间保存的数据拷贝到新的内存空间 } free(stack->data); stack->data = New_data; } stack->data[stack->size++] = value; return; }
void Pop(SeqStack* stack) { if(stack == NULL) { return; } if(stack->size == 0) { return; } --stack->size; return; }
int front(SeqStack* stack,stacktype* value) { if(stack == NULL || value == NULL) { return -1; } if(stack->size == 0) { return -1; } *value = stack->data[stack->size-1]; return 0; }
二、链式栈
链式栈就相对来说简单一点,尾插尾删就能满足条件。
stack.h #pragma once #include<stdio.h> typedef char LinkStackType; typedef struct LinkStack { LinkStackType data; struct LinkStack* next; }LinkStack; void Init(LinkStack** stack);//初始化 void Destory(LinkStack* stack);//销毁 void Push(LinkStack** stack,LinkStackType value);//压栈 void Pop(LinkStack** stack);//出栈 int Front(LinkStack* stack,LinkStackType* value);//取栈顶元素
stqck.c #include<stdio.h> #include"stack.h" #include<stdlib.h> void Init(LinkStack** stack) { if(stack == NULL) { return; } *stack = NULL; }
void DestoryStack(LinkStack** stack) { if(stack == NULL) { return; } LinkStack* to_delete = *stack; while(to_delete != NULL) { LinkStack* node = to_delete->next; free(to_delete); to_delete = node; } *stack = NULL; return; }
void Destory(LinkStack* node) { free(node); return; } LinkStack* CreatedNode(LinkStackType value) { LinkStack* New_Node = (LinkStack*)malloc(sizeof(LinkStack)); New_Node->data = value; New_Node->next = NULL; return New_Node; }
void Push(LinkStack** stack,LinkStackType value) { if(stack == NULL) { return; } LinkStack* new_node = CreatedNode(value); new_node->next = *stack; *stack = new_node; return; }
void Pop(LinkStack** stack) { if(stack == NULL) { return; } if(*stack == NULL) { //空链表 return; } LinkStack* to_delete = *stack; *stack = to_delete->next; Destory(to_delete); return; }
int Front(LinkStack* stack,LinkStackType* value) { if(stack == NULL || value == NULL) { return -1; } *value = stack->data; return 0; }
以下为测试代码:
void Test() { LinkStack* stack; LinkStackType value; Init(&stack); Push(&stack,'a'); Push(&stack,'b'); Push(&stack,'c'); Push(&stack,'d'); Front(stack,&value); printf("except d,actual %c\n",value); Pop(&stack); Front(stack,&value); printf("except c,actual %c\n",value); Pop(&stack); DestoryStack(&stack); Front(stack,&value); printf("except b,actual %c\n",value); Pop(&stack); Front(stack,&value); printf("except a,actual %c\n",value); Pop(&stack); DestoryStack(&stack); int ret = Front(stack,&value); printf("except -1,actual %d\n",ret); printf("except NULL,actual %c\n",value); } int main() { Test(); return 0; }