一、顺序栈
先进后出,后进先出
由于栈只有一边开口存取数据,称开口的那一端为“栈顶”,封死的那一端为“栈底”(类似于盛水的木桶,从哪进去的最后还得从哪出来)。
栈存储结构调取栈中数据元素时,要避免出现“上溢”和“下溢”的情况:
1、“上溢”:在栈已经存满数据元素的情况下,如果继续向栈内存入数据,栈存储就会出错。
2、“下溢”:在栈内为空的状态下,如果对栈继续进行取数据的操作,就会出错。
3、栈的“上溢”和“下溢”,可以总结为:栈满还存会“上溢”,栈空再取会“下溢”。
4、对于栈的两种表示方式来说,顺序栈两种情况都有可能发生;而链栈由于“随时需要,随时申请空间”的存储结构,不会出现“上溢”的情况。
栈操作数据元素只有两种动作:
1、数据元素用栈的数据结构存储起来,称为“入栈”,也叫“压栈”。
2、数据元素由于某种原因需要从栈结构中提取出来,称为“出栈”,也叫“弹栈”。
编写满递减栈
stack.c
#include <stdio.h>
#include <string.h>
#include "stack.h"
/*初始化栈*/
/**
*功能: 初始化栈 p;
*参数: 栈指针 p;
*返回值:无
**/
void init_stack(stack *p)
{
p->capacity = CAPCITY; //初始化栈的数据个数
p->top = p->capacity; //top指向栈底
}
/** 2、入栈
*功能: 将元素pe入栈p中;
*参数: 栈指针 p, 元素指针pe;
*返回值: 入栈成功返回0,入栈失败返回-1
**/
int push_stack(stack *p, int *pe)
{
if (p->top == 0)
{
return -1;
}
p->top--;
memcpy(p->data + p->top, pe,sizeof(int));
return 0;
}
/** 3、出栈
*功能: 将栈p中栈顶元素取出存入pe中;
*参数: 栈指针 p, 元素指针pe;
*返回值: 入栈成功返回0,入栈失败返回-1
**/
int pop_stack(stack *p, int *pe)
{
if (p->top == p-> capacity)
{
return -1;
}
memcpy(pe, p->data + p->top,sizeof(int));
p->top++;
return 0;
}
// 4、判断栈是否满
// 5、判断栈是否空
// 6、打印栈
/**
*功能:
*参数:栈指针p
*返回值:无
**/
void display(stack *p)
{
int i;
for (i = p->capacity-1; i >= p->top; i--)
{
printf ("%d\t",p->data[i]);
}
putchar('\n');
}
// 7、清空栈
stack.h
#ifndef _STACK_H_
#define _STACK_H_
//定义栈的容量
#define CAPCITY 10
//定义栈的类型
typedef struct
{
int data[CAPCITY];
int capacity;
int top;
}stack;
/** 1、初始化栈
*功能: 初始化栈 p;
*参数: 栈指针 p;
*返回值:无
**/
void init_stack(stack *p);
/** 2、入栈
*功能: 将元素pe入栈p中;
*参数: 栈指针 p, 元素指针pe;
*返回值: 入栈成功返回0,入栈失败返回-1
**/
int push_stack(stack *p, int *pe);
/** 3、出栈
*功能: 将栈p中栈顶元素取出存入pe中;
*参数: 栈指针 p, 元素指针pe;
*返回值: 入栈成功返回0,入栈失败返回-1
**/
int pop_stack(stack *p, int *pe);
// 4、判断栈是否满
/**
*功能:
*参数:栈指针p
*返回值:无
**/
static inline int full(stack *p)
{
return p->top == 0;
}
// 5、判断栈是否空
/**
*功能:
*参数:栈指针p
*返回值:无
**/
static inline int empty(stack *p)
{
return p->top == p->capacity;
}
// 6、打印栈
/**
*功能:
*参数:栈指针p
*返回值:无
**/
void display(stack *p);
// 7、清空栈
/**
*功能:
*参数:栈指针p
*返回值:无
**/
static inline int clear(stack *p)
{
p->top = p->capacity;
}
#endif
main函数
#include <stdio.h>
#include "stack.h"
int main()
{
int num[] = {10,12,5,6,13,9,14,8};
int i , n;
stack p;
init_stack(&p);
for (i = 0; i < sizeof(num)/sizeof(int); i++)
{
if (-1 == push_stack(&p, &num[i]))
{
printf ("入栈失败\n");
if (full(&p))
{
printf ("栈满\n");
break;
}
}
}
printf ("打印栈元素\n");
display(&p);
if (-1 == pop_stack(&p, &n))
{
printf ("出栈错误\n");
}
printf("打印栈元素\n");
display(&p);
if (empty(&p))
{
printf ("栈空\n");
}
clear(&p);
if (empty(&p))
{
printf ("栈情况: ");
printf ("栈空\n");
}
return 0;
}
二、链栈
#include <stdio.h>
#include <stdlib.h>
typedef struct lineStack
{
int data;
struct lineStack *next;
}lineStack;
lineStack *push(lineStack *stack, int a)
{
lineStack *line=(lineStack *)malloc(sizeof(lineStack));
line->data = a;
line->next = stack;
stack=line;
return stack;
}
lineStack *pop(lineStack *stack)
{
if (stack)
{
lineStack *p=stack;
stack=stack->next;
printf ("弹栈元素:%d",stack->data);
if (stack)
{
printf ("栈顶元素:%d\n",stack->data);
}
else
{
printf ("栈已空\n");
}
free(p);
}
else
{
printf ("栈内没有元素\n");
return stack;
}
return stack;
}
int main()
{
lineStack *stack=NULL;
stack=push(stack,1);
stack=push(stack,2);
stack=push(stack,3);
stack=push(stack,4);
stack=pop(stack);
stack=pop(stack);
stack=pop(stack);
stack=pop(stack);
stack=pop(stack);
return 0;
}
三、队列
#include <stdio.h>
//入队
int enqueue(int *a, int rear, int data)
{
a[rear]=data;
rear++;
return rear;
}
//出队
void lequeue(int *a, int froat, int rear)
{
while (froat != rear)
{
printf ("出队元素:%d\n",a[froat]);
froat++;
}
}
int main()
{
int a[100];
int froat,rear;
froat=rear=0;
rear=enqueue(a, rear,1);
rear=enqueue(a, rear,2);
rear=enqueue(a, rear,3);
rear=enqueue(a, rear,4);
rear=enqueue(a, rear,5);
lequeue(a, froat, rear);
return 0;
}
队列是线性表的一种,在操作数据元素时,和栈一样,有自己的规则:使用队列存取数据元素时,数据元素只能从表的一端进入队列,另一端出队列。
1、环状顺序队列
queue.c
#include <stdio.h>
#include <string.h>
#include "queue.h"
// 1、初始化队列
/**
*功能:初始化队列p
*参数:p队列指针
*返回值:无
**/
void init_queue(queue *p)
{
p->capacity = CAPACITY;
p->front = p->rear = 0;
}
//2、入队
/**
*功能:将元素pe入队列p中
*参数:p队列指针;pe元素指针用于提供数据
*返回值:成功返回 0;失败返回-1
**/
int enqueue(queue *p, int *pe)
{
if (full(p))
{
return -1;
}
memcpy(p->data + p->rear,pe,sizeof(int));
p->rear = (p->rear + 1)%p->capacity;//通过除以容量实现一个轮回的功能
return 0;
}
//3、出队
/**
*功能:从队列p中出队,数据保存到pe中
*参数:p队列指针;pe元素指针,用于存储数据
*返回值:成功返回0,失败返回-1
**/
int dequeue(queue *p, int *pe)
{
if (empty(p))
{
return -1;
}
memcpy(pe, p->data+p->front,sizeof(int ));
p->front = (p->front + 1) % p->capacity;//通过除以容量实现一个轮回的功能
return 0;
}
//4、判断队列是否满
//5、判断队列是否空
//6、打印队列
/**
*功能:打印队列p
*参数:p队列指针
*返回值:无
**/
void display(queue *p)
{
int i;
for (i = p->front;i%p->capacity != p->rear;i = (i+1)%p->capacity)//避免出现尾在头前面的情况
{
printf ("%d\t",p->data[i]);
}
putchar('\n');
}
//7、获取队列中元素(队头、队尾等)
/**
*功能:获取队列p的对头元素
*参数:p队列指针;pe元素指针用于存储数据
*返回值:成功返回0,失败返回-1
**/
int get_front(queue *p , int *pe)
{
if (empty(p))
{
return -1;
}
memcpy(pe,p->data+p->front,sizeof(int));
return 0;
}
//8、获取队列长度
//9、清空队列
queue.h
#ifndef _QUEUE_H_
#define _QUEUE_H_
#define CAPACITY 10
typedef struct
{
int capacity; // 队列容量
int front; // 队头指针
int rear; // 队尾指针
int data[CAPACITY]; // 队空间
} queue;
// 1、初始化队列
/**
*功能:初始化队列p
*参数:p队列指针
*返回值:无
**/
void init_queue(queue *p);
//2、入队
/**
*功能:将元素pe入队列p中
*参数:p队列指针;pe元素指针用于提供数据
*返回值:成功返回 0;失败返回-1
**/
int enqueue(queue *p, int *pe);
//3、出队
/**
*功能:从队列p中出队,数据保存到pe中
*参数:p队列指针;pe元素指针,用于存储数据
*返回值:成功返回0,失败返回-1
**/
int dequeue(queue *p, int *pe);
//4、判断队列是否满
/**
*功能:判断队列p是否已满
*参数:p队列指针
*返回值:已满返回1,未满返回0
**/
static inline int full(queue *p)
{
return (p->rear+1)%p->capacity == p->front;
}
//5、判断队列是否空
/**
*功能:判断队列 p是否为空
*参数:p队列指针
*返回值:队空返回1,队不空返回0
**/
static inline int empty(queue *p)
{
return p->rear == p->front;
}
//6、打印队列
/**
*功能:打印队列p
*参数:p队列指针
*返回值:无
**/
void display(queue *p);
//7、获取队列中元素(队头、队尾等)
/**
*功能:获取队列p的对头元素
*参数:p队列指针;pe元素指针用于存储数据
*返回值:成功返回0,失败返回-1
**/
int get_front(queue *p , int *pe);
//8、获取队列长度
/**
*功能:获取队列 p 的长度
*参数:p队列指针
*返回值:队列长度
**/
static inline int length(queue *p)
{
return (p->rear + p->capacity - p->front) % p->capacity;
}
//9、清空队列
/**
*功能:清空队列p
*参数:p队列指针
*返回值:无
**/
static inline void clear(queue *p)
{
p->rear = p->front;
}
#endif
main.c
#include <stdio.h>
#include "queue.h"
int main()
{
queue p;
int num[] = {1,2,3,4,5,6,7,8,9};
int i, n;
init_queue(&p);
for (i = 0; i < sizeof(num)/sizeof(int); i++)
{
if(-1 == enqueue(&p,&num[i]))
{
printf ("入队失败!\n");
if (full(&p))
{
printf ("队满\n");
break;
}
}
}
printf ("打印队元素:");
display(&p);
if (-1 == dequeue(&p,&n))
{
printf ("出队失败!\n");
}
printf ("打印出队之后的元素!\n");
display(&p);
if (-1 == get_front(&p,&n))
{
printf ("获取队头元素成功!\n");
}
else
{
printf ("获取队头元素失败!\n");
}
printf ("获取队长:%d\n",length(&p));
clear(&p);
printf ("队情况: ");
if (empty(&p))
{
printf ("队空\n");
}
return 0;
}