栈
-
栈:在表尾进行插入和删除的操作受限的线性表
-
逻辑结构:线性结构【一对一的关系】
-
存储结构:顺序存储【顺序栈】、链式存储【链栈】
-
栈的特点:
先进后出【first in last out FILO表】
后进先出【last in first out LIFO表】 -
栈的入栈和出栈
顺序栈
- 认识栈空、栈满
栈的插入
/*
* function: 入栈
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int list_stack_push(datatype e,StackList *stack)
{
//1,判断栈是否创建
//2,判断栈是否为满
if(NULL==stack || stack->top==MAXSIZE-1)
{
puts("push stack error");
return -1;
}
//3,入栈:先加后压
//stack->top++;
stack->data[++stack->top]=e;
return 0;
}
栈的删除
/*
* function: 出栈
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int list_stack_pop(StackList *stack)
{
//1,判断栈是否创建
//2,判断栈是否为空
if(NULL==stack || stack->top==-1)
{
puts("pop error");
return -1;
}
//3,出栈:先弹后减
printf("pop data is:%d\n",stack->data[stack->top--]);
// stack->top--;
return 0;
}
栈的遍历
/*
* function: 顺序栈的输出
* @param [ in]
* @param [out]
* @return 无
*/
void stack_output(StackList *stack)
{
//1,判断栈是否创建
//2,判断栈是否为空
if(NULL==stack || stack->top==-1)
{
puts("output error");
return;
}
//3,输出
for(int i=0;i<=stack->top;i++)
{
printf("%d\t",stack->data[i]);
}
puts("");
}
栈的创建
/*
* function: 创建栈
* @param [ in]
* @param [out]
* @return
*/
StackList *create_stack()
{
StackList *stack=(StackList *)malloc(sizeof(StackList));
if(NULL == stack)
{
return NULL;
}
//栈顶置空
stack->top=-1;
memset(stack->data,0,sizeof(stack->data));
return stack;
}
链栈
- 顺序栈存在栈满、并且存储数据量小,所以引出链栈,链栈采用链式存储结构,没有栈满,动态申请空间,多适用于数据量较大的情况
链栈节点创建【单链表节点创建】
/*
* function: 创建一个节点
* @param [ in]
* @param [out]
* @return
*/
LinkStack create_node()
{
LinkStack node=(LinkStack)malloc(sizeof(struct Node));
if(NULL==node)
return NULL;
node->data=0;
node->next=NULL;
return node;//0x10
}
链栈插入
/*
* function: 链栈的入站
* @param [ in]
* @param [out]
* @return
*/
LinkStack link_stack_push(datatype e,LinkStack top)
{
//在堆区创建一个节点
LinkStack node=create_node();//在堆区申请一个节点
node->data=e;//数据域赋值为e
//node节点链接到链表中
node->next=top;
top=node;
return top;//因为自定义函数指针的改变不影响实参,需要返回
}
链栈删除
/*
* function: 头删除
* @param [ in]
* @param [out]
* @return
*/
LinkStack link_stack_pop(LinkStack top)
{
//判断链表是否为空
if(NULL==top)
{
return top;
}
if(top->next==NULL)
{
free(L);
L=NULL;
}
else
{
LinkStack q=top->next;
top->data=q->data;
top->next=q->next;
free(q);
q=NULL;
}
return top;
}
链栈遍历
/*
* function: 循环遍历
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int link_output(LinkStack top)
{
//判断是否创建
//判断是否为空
if(NULL==top )
{
return -1;
}
while(top!=NULL)
{
printf("%d\t",top->data);
top=top->next;
}
puts("");
}
队列
- 线性表长度:数组长度(不变)
- 队头:第一个元素的下标
- 队尾:最后一个元素后面的下标(方便下一个元素的插入)
- 队空:队头==队尾
- 队满:rear=MAXSIZE
- 结构体定义
顺序队列
创建
/*
* function: 在堆区申请空间
* @param [ in]
* @param [out]
* @return 返回地址
*/
QueueList *create_queue()
{
QueueList *queue=(QueueList *)malloc(sizeof(QueueList));
if(NULL==queue)
return NULL;
queue->front=queue->rear=0;
memset(queue->data,0,sizeof(queue->data));
return queue;
}
入队
/*
* function: 入队
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int enqueue(datatype e,QueueList *queue)
{
//1,判断是否创建
//2,判断是否满
if(NULL==queue || queue->rear==MAXSIZE)
{
puts("enqueue error");
return -1;
}
//3,入队:在队尾插入
queue->data[queue->rear++]=e;
// queue->rear++;
return 0;
}
出队
/*
* function: 出队
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int delqueue(QueueList *queue)
{
//1,判断是否创建
//2,判断是否为空
if(NULL==queue || queue->front==queue->rear)
{
puts("delqueue error");
return -1;
}
//3,出队:出队在队头
printf("delqueue data is:%d\n",queue->data[queue->front++]);
// queue->front++;
}
遍历
/*
* function: 循环输出队列
* @param [ in]
* @param [out]
* @return 无
*/
void output(QueueList *queue)
{
//1,判断是否创建
//2,判断是否为空
if(NULL==queue || queue->front==queue->rear)
{
puts("output error");
return;
}
//3,从队头到队尾输出
for(int i=queue->front;i<queue->rear;i++)
{
printf("%d\t",queue->data[i]);
}
puts("");
}
循环队列
- 因为顺序队列的使用是一次性的,会出现假溢问题,因此引出循环队列,解决溢出问题。
入队
/*
* function: 循环队列入队
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int enqueue(datatype e,QueueList *queue)
{
//1,判断是否创建
//2,判断是否满
if(NULL==queue ||queue->front==(queue->rear+1)%MAXSIZE)
{
puts("enqueue error");
return -1;
}
//3,入队:在队尾插入
queue->data[queue->rear]=e;
queue->rear=(queue->rear+1)%MAXSIZE;
return 0;
}
出队
/*
* function: 出队
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int delqueue(QueueList *queue)
{
//1,判断是否创建
//2,判断是否为空
if(NULL==queue || queue->front==queue->rear)
{
puts("delqueue error");
return -1;
}
//3,出队:出队在队头
printf("delqueue data is:%d\n",queue->data[queue->front]);
queue->front=(queue->front+1)%MAXSIZE;
return 0;
}
遍历
/*
* function: 循环输出队列
* @param [ in]
* @param [out]
* @return 无
*/
void output(QueueList *queue)
{
//1,判断是否创建
//2,判断是否为空
if(NULL==queue || queue->front==queue->rear)
{
puts("output error");
return;
}
//3,从队头到队尾输出
for(int i=queue->front;i!=queue->rear;i=(i+1)%MAXSIZE)
{
printf("%d\t",queue->data[i]);
}
puts("");
}
个数计算
/*
* function: 计算循环队列个数
* @param [ in]
* @param [out]
* @return
*/
int loop_queue_count(QueueList *queue)
{
return (MAXSIZE-queue->front+queue->rear)%MAXSIZE;
}
链式队列
- 因为循环队列存在队满的情况,且适用于数据量较小的时候,因此引出了链式队列,存储类型不同,不存在队满,可以存储数据量较多的时候
创建
/*
* function: 创建一个节点
* @param [ in]
* @param [out]
* @return
*/
Linklist create_node()
{
Linklist node=(Linklist)malloc(sizeof(struct Node));
if(NULL==node)
return NULL;
node->data=0;
node->next=NULL;
return node;//0x10
}
入队
/*
* function: 尾插
* @param [ in]
* @param [out]
* @return
*/
Linklist insert_rear(datatype e,Linklist L)
{
//创建一个新节点
Linklist s=create_node();
s->data=e;
if(L==NULL)
{
L=s;
}
else
{
//rear指向最后一个节点的地址
Linklist rear=L;
while(rear->next!=NULL)
{
rear=rear->next;
}
rear->next=s;
}
return L;
}
出队
/*
* function: 头删除
* @param [ in]
* @param [out]
* @return
*/
Linklist delete_head(Linklist L)
{
//判断链表是否为空
if(NULL==L)
{
return L;
}
printf("delete data is:%d\n",L->data);
if(L->next==NULL)
{
free(L);
L=NULL;
}
else
{
Linklist q=L->next;
L->data=q->data;
L->next=q->next;
free(q);
q=NULL;
}
return L;
}
遍历
/*
* function: 循环遍历
* @param [ in]
* @param [out]
* @return 成功返回0 失败返回-1
*/
int link_output(Linklist L)
{
//判断是否创建
//判断是否为空
if(NULL==L )
{
return -1;
}
while(L!=NULL)
{
printf("%d\t",L->data);
L=L->next;
}
puts("");
}