栈与队列
栈
定义:
栈(Stack),是运算受限的线性表,插入和取出操作都只能在表头进行,也称之为后进先出(LIFO)线性表;
案例:
有名为stk的栈,按顺序插入:1,2,3三个元素,插入完成后取出全部,顺序为:3,2,1;
栈的实现:
既然是线性表,则可以通过顺序结构和链接结构来实现,通过顺序结构实现的栈称为顺序栈,通过链接结构实现的栈称为链栈;
常用操作:
- 初始化
- 入栈
- 出栈
- 取栈顶元素
- 空栈判断
使用场景:
程序中函数(方法)的执行通常都是借助栈来完成的,当要执行一个函数时,会将函数代码压入栈中,执行完毕则出栈,执行过程中若调用了其他函数,则被调函数同样会入栈,所以程序中的函数嵌套调用时,也是遵循后进先出;
顺序实现
顺序栈数据结构:
c语言实现:
#include <stdio.h>
//栈的顺序实现
//定义数据结构
const int SIZE = 5;
typedef struct{
int data[SIZE];
int top;
}seqStk,*SEQStack;
SEQStack initalStack(){
SEQStack stack = malloc(sizeof(seqStk));
stack->top = -1;
return stack;
}
int isEmpty(SEQStack stack){
if(stack->top == -1){
return 1;
}
return 0;
}
int getTop(SEQStack stack){
if (isEmpty(stack)) {
printf("err:stack is empty!\n");
return NULL;
}else{
return stack->data[stack->top];
}
}
int pop(SEQStack stack){
//先进后出,出栈是判断是否空
if (isEmpty(stack)) {
printf("err:stack is empty!\n");
return NULL;
}else{
int temp = getTop(stack);
stack->top--;
return temp;
}
}
void push(SEQStack stack,int data){
if (stack->top == SIZE-1) {
printf("err:stack already full!\n");
}else{
stack->top++;
stack->data[stack->top] = data;
}
}
int main(int argc, const char * argv[]) {
SEQStack stack = initalStack();
push(stack,100);
push(stack,200);
push(stack,300);
push(stack,400);
push(stack,500);
push(stack,600);
printf("geted:%d\n",pop(stack));
printf("geted:%d\n",getTop(stack));
printf("geted:%d\n",pop(stack));
printf("geted:%d\n",pop(stack));
printf("geted:%d\n",pop(stack));
printf("geted:%d\n",pop(stack));
printf("Hello, World!\n");
return 0;
}
双栈
顺序实现的弊端就在于,无法预估数据长度,会造成空间浪费,为了避免这个问题,我们可以让两个栈共享同一个顺序存储空间,起始地址和结束地址分别作为两个栈的栈底;
- 数据结构及相关操作:
链接实现
数据结构:
c语言实现:
#include <stdio.h>
//结构定义
typedef struct node{
int data;
struct node *next;
}Node,*LinkStk;
LinkStk initialStack(){
LinkStk stack = malloc(sizeof(Node));
stack->next = NULL;
return stack;
}
int isEmpty(LinkStk stack){
if (stack->next == NULL) {
return 1;
}
return 0;
}
void push(LinkStk stack,int data){
Node *p = malloc(sizeof(Node));
p->next = stack->next;
p->data = data;
stack->next = p;
}
Node *getTop(LinkStk stack){
return stack->next;
}
void *pop(LinkStk stack){
if (isEmpty(stack)) {
printf("error:stack is empty!\n");
return NULL;
}
Node *temp = stack->next;
stack->next = temp->next;
free(temp);
}
int main(int argc, const char * argv[]) {
LinkStk stack = initialStack();
push(stack, 100);
push(stack, 200);
push(stack, 300);
pop(stack);
pop(stack);
pop(stack);
Node *a = getTop(stack);
if (a != NULL){
printf("%d\n",a->data);
}
push(stack, 900);
Node *w = getTop(stack);
printf("%d\n",w->data);
printf("Hello, World!\n");
return 0;
}
案例中所有操作算法时间复杂度均为O(1);
队列
定义:
队列(Queue),同栈相同,也是运算受限的线性表,其插入只能在表未进行,而删除只能在表头进行,称之为先进先出(FIFO)线性表;
案例:
有名为stk的栈,按顺序插入:1,2,3三个元素,插入完成后取出全部,顺序为:1,2,3;
队列的实现:
既然是线性表,同样也可以通过顺序结构和链接结构来实现;
常用操作:
- 初始化
- 入队列
- 出队列
- 取队列首元素
- 空队列判断
使用场景:
队列的核心就在于,先来先得,先进队列的一定先出,这非常适合用在需要保证处理顺序的业务上,例如秒杀活动;
顺序实现
队列中的元素是具有顺序的所以可通过顺序结构实现,常见的方式就是通过数组,但是数组的问题是无法准确预估元素大小
此外,当有元素从队列中出去时,队列则可以存如储新的元素,但是心存储的元素应该放在那里却成了一个问题,
实现原理简述:
c语言实现:
#include <stdio.h>
const int max_size = 5;
//数据结构定义
typedef struct LQueue{
int data[max_size];
int front;
int rear;
}LQueue,*Queue;
//初始化
LQueue *initial(){
LQueue *queue = malloc(sizeof(LQueue));
queue->front = 0;
queue->rear = 0;
return queue;
}
//入队列
void put(LQueue *queue,int data){
if ((queue->rear+1)%max_size == queue->front){
printf("error:队列已满\n");
exit(-1);
} else{
queue->rear = (queue->rear+1)%max_size;
queue->data[queue->rear] = data;
}
}
//判空
int isEmpty(LQueue *queue){
return queue->rear == queue->front;
}
//出队列
int get(LQueue *queue){
if (isEmpty(queue)){
printf("error:队列为空");
exit(-1);
}else{
queue->front = (queue->front+1)%max_size;
return queue->data[queue->front];
}
}
//测试
int main(int argc, const char * argv[]) {
Queue queue = initial();
put(queue,1);
put(queue,2);
put(queue,3);
put(queue,4);
printf("%d\n",get(queue));
printf("%d\n",get(queue));
put(queue,5);
put(queue,6);
printf("%d\n",get(queue));
printf("%d\n",get(queue));
printf("%d\n",get(queue));
printf("%d\n",get(queue));
put(queue,7);
printf("%d\n",get(queue));
printf("Hello, World!\n");
return 0;
}
```![](https://img2020.cnblogs.com/blog/1440878/202004/1440878-20200423165956826-613812768.png)
![](https://img2020.cnblogs.com/blog/1440878/202004/1440878-20200423165959774-971029359.png)