1.栈的概念:
栈(
stack
)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新
元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶
元素删除掉,使其相邻的元素成为新的栈顶元素。
栈
(
Stack
):是只允许在一端进行插入或删除的线性表。首先栈是一
种线性表,
但限定这种线性表只能在某一端进行插入和删除操作。
栈顶
(
Top
):线性表允许进行插入删除的那一端。
栈底
(
Bottom
):固定的,不允许进行插入和删除的另一端。
空栈
:不含任何元素的空表。
栈又称为后进先出(
Last In First Out
)的线性表,简称
LIFO
结构
特性:
它的特殊之处在于限制了这个线性表的插入和删除的位置
,
它始终只在栈顶进行。这也就使
得
:
==
栈底是固定的
,
最先进栈的只能在栈底
==
。
对栈的操作:
示例如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_SIZE 50
typedef struct{
void *data[MAX_SIZE];
int size;
}Stack;
typedef struct{
char name[15];
int age;
char breed[10];
}Stu;
Stack *initstack(void){
Stack *stack=(Stack *)malloc(sizeof(Stack));
if(stack==NULL){
printf("malloc error.\n");
return NULL;
}
for(int i=0;i<MAX_SIZE;i++){
stack->data[i]=NULL;
}
stack->size=0;
return stack;
}
void pushstack(Stack *stack,void *data){
if(stack==NULL){
return;
}
if(stack->size==MAX_SIZE){
return;
}
if(data==NULL){
return;
}
stack->data[stack->size]=data;
stack->size++;
}
void popstack(Stack *stack){
if(stack==NULL){
return;
}
if(stack->size==0){
return;
}
stack->data[stack->size-1]=NULL;
stack->size--;
}
void *topelement(Stack *stack){
if(stack==NULL){
return NULL;
}
if(stack->size==0){
return NULL;
}
return stack->data[stack->size-1];
}
int isempty(Stack *stack){
if(stack==NULL){
return 0;
}
if(stack->size==0){
return 0;
}
return 1;
}
int sizestack(Stack *stack){
if(stack==NULL){
return -1;
}
return stack->size;
}
void clearstack(Stack *stack){
if(stack==NULL){
return;
}
for(int i=0;i<stack->size;i++){
stack->data[i]=NULL;
}
stack->size=0;
}
void freestack(Stack *stack){
if(stack==NULL){
return;
}
free(stack);
}
int main(){
Stack *stack=initstack();
Stu p1={"洛羽晨",18,"人类"};
Stu p2={"虚构康",20,"不详"};
Stu p3={"丁真",23,"出生"};
Stu p4={"谷爱凌",22,"剑冢"};
pushstack(stack,&p1);
pushstack(stack,&p2);
pushstack(stack,&p3);
pushstack(stack,&p4);
while(sizestack(stack)>0){
Stu *p=(Stu *)topelement(stack);
printf("name:%s,age=%d,breed=%s\n",p->name,p->age,p->breed);
popstack(stack);
}
freestack(stack);
return 0;
}
2.栈的链式存储结构:
概念:上面讲的是栈的顺序存储结构,相当于一个线性表,只是操作位置有限制。链式存储结构也就是链表形式的栈。它和链表的结构是一样的,操作方式和上面的一样。
操作:
示例如下:
#include "linkstack.h"
typedef struct
{
char name[64];
int age;
int score;
}Person;
//打印函数
void my_print(void *data)
{
Person *p=(Person *)data;
printf("name:%s age:%d score:%d\n",p->name,p->age,p->score);
}
int main()
{
//创建链表
LinkStack *stack=init_linkstack();
//获取链表长度
printf("stack 长度:%d\n",size_linkstack(stack));
//创建数据
//创建数据
Person p1={"aaa",10,80};
Person p2={"bbb",11,81};
Person p3={"ccc",12,82};
Person p4={"ddd",13,83};
//入栈
push_linkstack(stack, &p1);
push_linkstack(stack, &p2);
//打印
print_linkstack(stack, my_print);
printf("\n");
//入栈
push_linkstack(stack, &p3);
push_linkstack(stack, &p4);
//打印
print_linkstack(stack, my_print);
printf("\n");
//出栈
void *data=pop_linkstack(stack);
my_print(data);
printf("\n");
//打印
print_linkstack(stack, my_print);
printf("\n");
//获取链表长度
printf("stack 长度:%d\n",size_linkstack(stack));
//返回第一个结点
Person *p=(Person *)top_element(stack);
printf("top_element:name-%s,age-%d,score-%d\n",p->name,p->age,p->score);
//销毁
free_linkstack(stack);
return 0;
}
#include "linkstack.h"
//初始链表
LinkStack *init_linkstack(void)
{
LinkStack *stack=(LinkStack *)malloc(sizeof(LinkStack));
stack->size=0;
//头结点
stack->head=(LinkNode *)malloc(sizeof(LinkNode));
stack->head->data=NULL;
stack->head->next=NULL;
return stack;
}
//指定位置插入
void push_linkstack(LinkStack *stack, void *data)
{
if(stack == NULL)
{
return ;
}
if(data == NULL)
{
return ;
}
//创建新的结点
LinkNode *newnode=(LinkNode *)malloc(sizeof(LinkNode));
newnode->data=data;
newnode->next=NULL;
//找结点
//辅助指针变量
LinkNode *pcurrent=stack->head;
//新结点插入链表
newnode->next=pcurrent->next;
pcurrent->next=newnode;
stack->size++;
}
//删除指定位置的值
void *pop_linkstack(LinkStack *stack)
{
if(stack == NULL)
{
return NULL;
}
//找结点
//辅助指针变量
LinkNode *pcurrent=stack->head;
//删除结点
LinkNode *delnode=pcurrent->next;
pcurrent->next=delnode->next;
void *data=delnode->data;
free(delnode);
stack->size--;
return data;
}
//获取链表长度
int size_linkstack(LinkStack *stack)
{
return stack->size;
}
//返回栈顶元素数据域
void *top_element(LinkStack *stack)
{
return stack->head->next->data;
}
//打印栈内所有内容
void print_linkstack(LinkStack *stack, printlinknode print)
{
if(stack == NULL)
{
return ;
}
//辅助指针变量
LinkNode *pcurrent=stack->head->next;
while(pcurrent!=NULL)
{
print(pcurrent->data);
pcurrent=pcurrent->next;
}
}
//释放链表内存
void free_linkstack(LinkStack *stack)
{
if(stack == NULL)
{
return ;
}
//辅助指针变量
LinkNode *pcurrent=stack->head;
while(pcurrent!=NULL)
{
//缓存下一个结点
LinkNode *pnext=pcurrent->next;
free(pcurrent);
pcurrent=pnext;
}
//释放链表内存
stack->size=0;
free(stack);
}
#ifndef LINKLIST_H
#define LINKLIST_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#endif
//结点结构体
typedef struct NODE
{
void *data;
struct NODE *next;
}LinkNode;
//栈表结构体
typedef struct
{
LinkNode *head;
int size;
}LinkStack;
//打印函数指针
typedef void(*printlinknode)(void *);
//初始栈表
LinkStack *init_linkstack(void);
//入栈
void push_linkstack(LinkStack *stack, void *data);
//出栈
void *pop_linkstack(LinkStack *stack);
//获取链表长度
int size_linkstack(LinkStack *stack);
//返回第一个结点
void *top_element(LinkStack *stack);
//打印栈内结点
void print_linkstack(LinkStack *stack, printlinknode print);
//释放栈内存
void free_linkstack(LinkStack *stack);
2.队列的概念:
队列是一种特殊的
线性表
,特殊之处在于它只允许在表的前端(
front
)进行删除操作,而在表的后端(
rear
)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进
行删除操作的端称为队头。
![](https://i-blog.csdnimg.cn/blog_migrate/910e1cd94a204869b5d4d80a83350533.png)
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中
删除,
==
故队列又称为先进先出(
FIFO—first in first out
)
线性表
。
2.对队列的操作:
增删改查
示例如下:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 1024
typedef struct
{
void *data[MAX_SIZE];
int size;
}Queue;
//初始化
Queue * init_queue(void)
{
Queue *queue=(Queue *)malloc(sizeof(Queue));
for(int i=0;i<MAX_SIZE;i++)
{
queue->data[i]=NULL;
}
queue->size=0;
return queue;
}
//入队
void push_queue(Queue *queue, void *data)
{
//数组左边当做对头
if(queue==NULL)
{
return ;
}
if(data==NULL)
{
return ;
}
queue->data[queue->size]=data;
queue->size++;
}
//返回对头元素
void *front_queue(Queue *queue)
{
if(queue==NULL)
{
return NULL;
}
if(queue->size==0)
{
return NULL;
}
return queue->data[0];
}
//出队
void pop_queue(Queue *queue)
{
//需要移动元素
if(queue==NULL)
{
return ;
}
if(queue->size==0)
{
return ;
}
for(int i=0;i<queue->size-1;i++)
{
queue->data[i]=queue->data[i+1];
}
queue->size--;
}
//返回队尾元素
void *back_queue(Queue *queue)
{
if(queue==NULL)
{
return NULL;
}
if(queue->size==0)
{
return NULL;
}
return queue->data[queue->size-1];
}
//返回大小
int size_queue(Queue *queue)
{
if(queue==NULL)
{
return -1;
}
return queue->size;
}
//清空队列
void clear_queue(Queue *queue)
{
if(queue==NULL)
{
return ;
}
while(queue->size>0)
{
queue->size--;
queue->data[queue->size]=NULL;
}
}
//销毁
void free_queue(Queue *queue)
{
if(queue==NULL)
{
return ;
}
free(queue);
}
typedef struct
{
char name [64];
int age;
}Person;
int main()
{
//创建队列
Queue *queue=init_queue();
//创建数据
Person p1={"aaa",10};
Person p2={"bbb",10};
Person p3={"ccc",10};
Person p4={"ddd",10};
//入队
push_queue(queue,&p1);
push_queue(queue,&p2);
push_queue(queue,&p3);
push_queue(queue,&p4);
//取出对尾元素
Person *p=(Person *)back_queue(queue);
printf("name:%s, age=%d\n",p->name,p->age);
printf("\n");
clear_queue(queue);
printf("\n");
//入队
push_queue(queue,&p1);
push_queue(queue,&p2);
push_queue(queue,&p3);
push_queue(queue,&p4);
//输出
while(size_queue(queue)>0)
{
//取出对头元素
Person *p=(Person *)front_queue(queue);
printf("name:%s, age=%d\n",p->name,p->age);
//出队
pop_queue(queue);
}
//销毁队列
free_queue(queue);
return 0;
}