顺序表
特点:内存连续,数组
1)逻辑结构:线性结构
2)存储结构:顺序存储
3)操作:增删改查
函数名命名规则:
下滑线法:create_empty_seqlist
小驼峰法:createEmptySeqList
大驼峰法:CreateEmptySeqList
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
#include<stdio.h>
#include<stdlib.h>
#define N 5
typedef struct
{
int data[N];
int last;//last代表的是数组中最后一个有效元素的下标
}seqlist_t;
//1.创建一个空的顺序表
seqlist_t *CreateEpSeqlist();//返回的是申请空间的首地址
//2.向顺序表的指定位置插入数据
int InsertIntoSeqlist(seqlist_t *p, int post,int data);//post第几个位置,data插入的数据
//3.遍历顺序表sequence 顺序 list 表
void ShowSeqlist(seqlist_t *p);
//4.判断顺序表是否为满,满返回1 未满返回0
int IsFullSeqlist(seqlist_t *p);
//5.判断顺序表是否为空
int IsEpSeqlist(seqlist_t *p);
//6.删除顺序表中指定位置的数据post删除位置
int DeletePostSeqlist(seqlist_t *p, int post);
//7.清空顺序表
void ClearSeqList(seqlist_t *p);
//8.修改指定位置的数据
int ChangePostSeqList(seqlist_t *p,int post,int data);//post被修改的位置,data修改成的数据
//9.查找指定数据出现的位置
int SearchDataSeqList(seqlist_t *p,int data);//data代表被查找的数据
#endif
操作代码
#include "seqlist.h"
//1.创建一个空的顺序表
seqlist_t *CreateEpSeqlist()
{
//1.动态开辟一个结构体大小的空间
seqlist_t *p = (seqlist_t *)malloc(sizeof(seqlist_t));
if (p == NULL)
{
perror("malloc err");
}
//2.对last初始化
p->last = -1; //表示当前顺序表为空,无有效元素
return p;
}
//4.判断顺序表是否为满,满返回1 未满返回0
int IsFullSeqlist(seqlist_t *p)
{
return p->last + 1 == N;
}
//2.向顺序表的指定位置插入数据
int InsertIntoSeqlist(seqlist_t *p, int post, int data)
{
//1.容错判断
if (IsFullSeqlist(p) || post < 0 || post > p->last + 1)
{
printf("InsertIntoSeqlist err\n");
return -1;
}
for (int i = p->last; i >= post; i--)
{
p->data[i + 1] = p->data[i];
}
p->data[post] = data;
p->last++;
}
//3.遍历顺序表sequence 顺序 list 表
void ShowSeqlist(seqlist_t *p)
{
for (int i = 0; i <= p->last; i++)
{
printf("%d ", p->data[i]);
}
}
//5.判断顺序表是否为空
int IsEpSeqlist(seqlist_t *p)
{
return p->last == -1;
}
//6.删除顺序表中指定位置的数据post删除位置
int DeletePostSeqlist(seqlist_t *p, int post)
{
if (IsEpSeqlist(p) || post < 0 || post > p->last)
{
printf("DeletePostSeqlist err\n");
return -1;
}
for (int i = post; i <= p->last; i++)
{
p->data[i] = p->data[i + 1];
}
p->last--;
return 0;
}
//7.清空顺序表
void ClearSeqList(seqlist_t *p)
{
p->last = -1;
}
//8.修改指定位置的数据
int ChangePostSeqList(seqlist_t *p, int post, int data) //post被修改的位置,data修改成的数据
{
if (post < 0 || post > p->last)
{
printf("ChangePostSeqList err\n");
return -1;
}
p->data[post] = data;
return 0;
}
//9.查找指定数据出现的位置
int SearchDataSeqList(seqlist_t *p, int data) //data代表被查找的数据
{
if (IsEpSeqlist(p))
{
printf("SearchDataSeqList err\n");
return -1;
}
for (int i = 0; i <= p->last; i++)
if (p->data[i] == data)
//printf("%d", i);
return i;
return -1;
}
顺序表总结:
(1)顺序表在内存当中是连续存储的
(2)顺序表的长度是固定 //#define N 5
(3)顺序表查找数据的时候方便的,插入和删除麻烦
链表
解决了:长度固定,插入删除麻烦的问题
1)逻辑结构:线性结构
2)存储结构:链式存储结构
3)操作:增删改查
单向链表
无头单向链表
每个节点的数据域和指针域都有效
有头单向链表
存在一个头节点,头节点的数据域无效,但指针域有效
有头单向链表相关操作
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
typedef int datatype;
typedef struct node_t
{
datatype data;//数据域
struct node_t *next;//指针域,指向自身结构体的指针
}link_node_t,*link_list_t;
//1.创建一个空的单向链表(有头单向链表)
link_node_t *CreateEpLinkList();
//2.向单向链表的指定位置插入数据
//p保存链表的头指针 post 插入的位置 data插入的数据
int InsertIntoPostLinkList(link_node_t *p,int post, datatype data);
//3.遍历单向链表
void ShowLinkList(link_node_t *p);
//4.求单向链表长度的函数
int LengthLinkList(link_node_t *p);
//5.删除单向链表中指定位置的数据 post 代表的是删除的位置
int DeletePostLinkList(link_node_t *p, int post);
//6.判断单向链表是否为空 1代表空 0代表非空
int IsEpLinkList(link_node_t *p);
//7.修改指定位置的数据 post 被修改的位置 data修改成的数据
int ChangePostLinkList(link_node_t *p, int post, datatype data);
//8.查找指定数据出现的位置 data被查找的数据 //search 查找
int SearchDataLinkList(link_node_t *p, datatype data);
//9.删除单向链表中出现的指定数据,data代表将单向链表中出现的所有data数据删除
int DeleteDataLinkList(link_node_t *p, datatype data);
//10.转置链表
void ReverseLinkList(link_node_t *p);
//11.清空单向链表
void ClearLinkList(link_node_t *p);
#endif
操作代码
#include "link_list.h"
//1.创建一个空的单向链表(有头单向链表)
link_node_t *CreateEpLinkList()
{
link_list_t p=(link_list_t)malloc(sizeof(link_node_t));
if (p==NULL)
{
perror("malloc err");
return NULL;
}
p->next=NULL;
return p;
}
//4.求单向链表长度的函数
int LengthLinkList(link_node_t *p)
{
int len=0;
while (p->next!=NULL)
{
p=p->next;
len++;
}
return len;
}
//2.向单向链表的指定位置插入数据
//p保存链表的头指针 post 插入的位置 data插入的数据
int InsertIntoPostLinkList(link_node_t *p,int post, datatype data)
{
if(post<0||post>LengthLinkList(p))
{
perror("InsertIntoPostLinkList err\n");
return -1;
}
for (int i=0;i<post;i++)
{
p=p->next;
}
link_list_t pnew=(link_list_t)malloc(sizeof(link_node_t));
if(pnew==NULL)
{
perror("error");
return -1;
}
pnew->data=data;
pnew->next=NULL;
pnew->next=p->next;
p->next=pnew;
return 0;
}
//6.判断单向链表是否为空 1代表空 0代表非空
int IsEpLinkList(link_node_t *p)
{
return p->next==NULL;
}
//5.删除单向链表中指定位置的数据 post 代表的是删除的位置
int DeletePostLinkList(link_node_t *p, int post)
{
if(IsEpLinkList(p)||post<0||post>=LengthLinkList(p))
{
perror("DeletePostLinkList err\n");
return -1;
}
for (int i=0;i<post;i++)
{
p=p->next;
}
link_list_t pdel=p->next;
p->next=pdel->next;
free(pdel);
pdel=NULL;
return 0;
}
//3.遍历单向链表
void ShowLinkList(link_node_t *p)
{
while (p->next!=NULL)
{
p=p->next;
printf("%d ",p->data);
}
}
//7.修改指定位置的数据 post 被修改的位置 data修改成的数据
int ChangePostLinkList(link_node_t *p, int post, datatype data)
{
if(IsEpLinkList(p)||post<0||post>=LengthLinkList(p))
{
perror("ChangePostLinkList err\n");
return -1;
}
for (int i=0;i<=post;i++)
{
p=p->next;
}
p->data=data;
return 0;
}
//8.查找指定数据出现的位置 data被查找的数据 //search 查找
int SearchDataLinkList(link_node_t *p, datatype data)
{
if(IsEpLinkList(p))
{
perror("SearchDataLinkList err\n");
return -1;
}
int n=LengthLinkList(p);
for (int i=0;i<n;i++)
{
p=p->next;
if(p->data==data)
{
printf("%d ",i);
}
}
return 0;
}
//11.清空单向链表
void ClearLinkList(link_node_t *p)
{
link_list_t pdel=NULL;
while(p->next!=NULL)
{
pdel=p->next;
p->next=pdel->next;
free(pdel);
pdel=NULL;
}
}
//10.转置链表
void ReverseLinkList(link_node_t *p)
{
link_list_t t;
link_list_t q;
q=p->next;
p->next=NULL;
while(q)
{
t=q;
q=q->next;
t->next=p->next;
p->next=t;
}
}
//9.删除单向链表中出现的指定数据,data代表将单向链表中出现的所有data数据删除
int DeleteDataLinkList(link_node_t *p, datatype data)
{
link_list_t pdel=NULL;
link_list_t q=p->next;
while (q!=NULL)
{
if(q->data==data)
{
pdel=q;
p->next=pdel->next;
free(pdel);
pdel=NULL;
q=p->next;
}
else
{
p=p->next;
q=p->next;
}
}
return 0;
}
总结:
顺序表和链表的区别?
(1)顺序表在内存当中连续存储的(数组),但是链表在内存当中是不连续存储的,通过指针将数据链接在一起
(2)顺序表的长度是固定的,但是链表长度不固定
(3)顺序表查找方便,但是插入和删除麻烦,链表,插入和删除方便,查找麻烦
双向链表
#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct node_t
{
datatype data;//数据域
struct node_t *next;//指向下一个节点的指针 next 下一个
struct node_t *prior;//指向前一个节点的指针 prior 前一个
}link_node_t,*link_list_t;
//将双向链表的头指针和尾指针封装到一个结构体里
//思想上有点像学的链式队列
typedef struct doublelinklist
{
link_list_t head; //指向双向链表的头指针
link_list_t tail; //指向双向链表的尾指针
int len;
}double_node_t,*double_list_t;
//1.创建一个空的双向链表
double_list_t createEmptyDoubleLinkList();
//2.向双向链表的指定位置插入数据 post位置, data数据
int insertIntoDoubleLinkList(double_list_t p, int post, datatype data);
//3.遍历双向链表
void showDoubleLinkList(double_list_t p);
//4.删除双向链表指定位置的数据
int deletePostDoubleLinkList(double_list_t p, int post);
//5.判断双向链表是否为空
int isEmptyDoubleLinkList(double_list_t p);
//6.求双向链表的长度
int lengthDoubleLinkList(double_list_t p);
//7.查找指定数据出现的位置 data被查找的数据
int searchPostDoubleLinkList(double_list_t p,datatype data);
//8.修改指定位置的数据,post修改的位置 data被修改的数据
int changeDataDoubleLinkList(double_list_t p,int post, datatype data);
//9.删除双向链表中的指定数据 data代表删除所有出现的data数据
int deleteDataDoubleLinkList(double_list_t p, datatype data);
相关操作
#include "linklist.h"
//1.创建一个空的双向链表
double_list_t createEmptyDoubleLinkList()
{
double_list_t p = (double_list_t)malloc(sizeof(double_node_t));
if (p == NULL)
{
perror("error1\n");
return NULL;
}
p->len = 0;
p->tail = p->head = (link_list_t)malloc(sizeof(link_node_t));
if (p->head == NULL)
{
perror("error2\n");
return NULL;
}
p->head->next = NULL;
p->head->prior = NULL;
return p;
}
//2.向双向链表的指定位置插入数据 post位置, data数据
int insertIntoDoubleLinkList(double_list_t p, int post, datatype data)
{
link_list_t temp = NULL;
if (post < 0 || post > p->len)
{
perror("error3\n");
return -1;
}
//创建一个新的节点存放数据
link_list_t pnew = (link_list_t)malloc(sizeof(link_node_t));
if (pnew == NULL)
{
perror("error4\n");
return -1;
}
//初始化节点
pnew->data = data;
pnew->next = NULL;
pnew->prior = NULL;
//插入链表
//对插入位置进行判断
if (post == p->len) //尾插
{
p->tail->next = pnew;
pnew->prior = p->tail;
p->tail = pnew; //将指针指向此时尾节点
}
else //后半段,尾指针
{
//1)将temp移动到被插入的位置
if (post < p->len / 2) //前半段,头指针
{
temp = p->head;
for (int i = 0; i <= post; i++) //从前往后遍历
temp = temp->next;
}
else
{
temp = p->tail;
for (int i = 0; i < p->len - post; i++) //从后往前遍历
temp = temp->prior;
}
//先连后面再连前面
temp->prior->next = pnew;
pnew->prior = temp->prior;
pnew->next = temp;
temp->prior = pnew;
}
p->len++; //链表长度加一
return 0;
}
//5.判断双向链表是否为空
int isEmptyDoubleLinkList(double_list_t p)
{
return p->len == 0;
}
//3.遍历双向链表
void showDoubleLinkList(double_list_t p)
{
if (isEmptyDoubleLinkList(p))
{
perror("error5\n");
}
else
{
link_list_t temp = p->head;
printf("正向遍历:\n");
while (temp->next != NULL)
{
temp = temp->next;
printf("%d ", temp->data);
}
printf("\n");
temp = p->tail;
printf("反向遍历:\n");
while (temp != p->head)
{
printf("%d ", temp->data);
temp = temp->prior;
}
}
}
//4.删除双向链表指定位置的数据
int deletePostDoubleLinkList(double_list_t p, int post)
{
link_list_t temp = NULL;
//容错判断
if (isEmptyDoubleLinkList(p) || post < 0 || post >= p->len)
{
perror("error6\n");
return -1;
}
//判断位置
if (post == p->len - 1) //尾删
{
p->tail = p->tail->prior;
free(p->tail->next);
p->tail->next = NULL; //将指针指向此时尾节点
}
else //后半段,尾指针
{
//1)将temp移动到被删除的位置
if (post < p->len / 2) //前半段,头指针
{
temp = p->head;
for (int i = 0; i <= post; i++) //从前往后遍历
temp = temp->next;
}
else
{
temp = p->tail;
for (int i = 0; i < p->len - post; i++) //从后往前遍历
temp = temp->prior;
}
//删除操作
temp->prior->next = temp->next;
temp->next->prior = temp->prior;
free(temp);
temp = NULL;
}
p->len--;
return 0;
}
//6.求双向链表的长度
int lengthDoubleLinkList(double_list_t p)
{
return p->len;
}
//7.查找指定数据出现的位置 data被查找的数据
int searchPostDoubleLinkList(double_list_t p, datatype data)
{
//遍历依次查找数据
link_list_t q = p->head;
int n = 0;
while (q->next != NULL)
{
q = q->next;
if (q->data == data)
return n;
n++;
}
return -1;
}
//8.修改指定位置的数据,post修改的位置 data被修改的数据
int changeDataDoubleLinkList(double_list_t p, int post, datatype data)
{
link_list_t temp = NULL;
if (isEmptyDoubleLinkList(p) || post < 0 || post >= p->len)
{
perror("error8\n");
return -1;
}
if (post < p->len / 2) //前半段,头指针
{
temp = p->head;
for (int i = 0; i <= post; i++) //从前往后遍历
temp = temp->next;
}
else
{
temp = p->tail;
for (int i = 0; i < p->len - post; i++) //从后往前遍历
temp = temp->prior;
}
temp->data = data;
return 0;
}
//9.删除双向链表中的指定数据 data代表删除所有出现的data数据
int deleteDataDoubleLinkList(double_list_t p, datatype data)
{
link_list_t pdel = NULL;
link_list_t h = p->head->next;
while (h != NULL)
{
if (h->data == data)
{
if (h == p->tail)
{
p->tail = p->tail->prior;
free(p->tail->next);
p->tail->next = NULL;
}
else
{
h->prior->next = h->next;
h->next->prior = h->prior;
pdel = h;
h = h->next;
free(pdel);
pdel = NULL;
}
p->len--;
}
else
{
h = h->next;
}
}
return 0;
}
int main(int argc, char const *argv[])
{
double_list_t p = createEmptyDoubleLinkList();
for (int i = 0; i <= 5; i++)
insertIntoDoubleLinkList(p, i, i + 1);
showDoubleLinkList(p);
printf("\n");
printf("%d \n", searchPostDoubleLinkList(p, 5));
deleteDataDoubleLinkList(p, 5);
while (!isEmptyDoubleLinkList(p))
{
deletePostDoubleLinkList(p, 0);
}
showDoubleLinkList(p);
free(p->head);
p->head = NULL;
return 0;
}
栈
1.概念:
只能在一端进行插入和删除操作的线性表,进行插入和删除的一端叫做栈顶,另一端叫做栈底。
2.特点:
先入后出,后入先出
FILO,LIFO
顺序栈:seqstack
1)逻辑结构:线性结构
2)存储结构:顺序存储
3)操作:
#ifndef _SEQSTACK_H_
#define _SEQSTACK_H_
typedef struct seqstack
{
int* data;//指向栈的存储位置
int maxlen;//保存栈的最大长度
int top;//称为栈针,用的时候,心里面可以将按照顺序表里的last来使用
//top 始终代表当前栈内最后一个有效元素的下标
}seqstack_t;
//1.创建一个空的栈
seqstack_t *CreateEpSeqStack(int len);//len代表的是创建栈的时候的最大长度
//2.判断是否为满,满返回1 未满返回0
int IsFullSeqStack(seqstack_t *p);
//3.入栈
int PushStack(seqstack_t *p, int data);//data代表入栈的数据
//4.判断栈是否为空
int IsEpSeqStack(seqstack_t *p);
//5.出栈
int PopSeqStack(seqstack_t *p);
//6. 清空栈
void ClearSeqStack(seqstack_t *p);
//7. 获取栈顶数据(注意不是出栈操作,如果出栈,相当于删除了栈顶数据,只是将栈顶的数据获取到,不需要移动栈针)
int GetTopSeqStack(seqstack_t *p);
//8. 求栈的长度
int LengthSeqStack(seqstack_t *p);
#endif
相关操作代码
#include<stdio.h>
#include<stdlib.h>
#include "seqstack.h"
seqstack_t *CreateEpSeqStack(int len)
{
seqstack_t *p=(seqstack_t *)malloc(sizeof(seqstack_t));
if (p==NULL)
{
perror("error1\n");
return NULL;
}
p->maxlen=len;
p->top=-1;
p->data =(int *)malloc(sizeof(int)*len);
if(p->data==NULL)
{
perror("p->data malloc err\n");
return NULL;
}
return p;
}
//2.判断是否为满,满返回1 未满返回0
int IsFullSeqStack(seqstack_t *p)
{
return p->top+1==p->maxlen;
}
//3.入栈
int PushStack(seqstack_t *p, int data)//data代表入栈的数据
{
if (IsFullSeqStack(p))
{
perror("PushStack err\n");
return -1;
}
p->top++;
p->data[p->top]=data;
return 0;
}
//4.判断栈是否为空
int IsEpSeqStack(seqstack_t *p)
{
return p->top==-1;
}
//5.出栈
int PopSeqStack(seqstack_t *p)
{
if(IsEpSeqStack(p))
{
perror("PopSeqStack err\n");
return -1;
}
p->top--;
return p->data[p->top+1];
}
//6. 清空栈
void ClearSeqStack(seqstack_t *p)
{
p->top=-1;
}
//7. 获取栈顶数据(注意不是出栈操作,如果出栈,相当于删除了栈顶数据,只是将栈顶的数据获取到,不需要移动栈针)
int GetTopSeqStack(seqstack_t *p)
{
if(!IsEpSeqStack(p))
return p->data[p->top];
return -1;
}
//8. 求栈的长度
int LengthSeqStack(seqstack_t *p)
{
return p->top+1;
}
链式栈
1)逻辑结构:线性结构
2)存储结构:链式存储
3)操作:
#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_
#include <stdio.h>
#include <stdlib.h>
//入栈和出栈只在第一个节点位置操作
typedef int datatype;
typedef struct linkstack
{
datatype data;//数据域
struct linkstack *next;//指针域
}linkstack_t;
//1.创建一个空的栈
void CreateEpLinkStack(linkstack_t **ptop);
//2.入栈 data是入栈的数据
参数上之所以采用二级指针,因为我们要随着入栈添加新的节点作为头,top需要永远指向当前链表的头,
那么修改main函数中的top,我们采用地址传递
int PushLinkStack(linkstack_t **ptop, datatype data);
//3.判断栈是否为空
int IsEpLinkStack(linkstack_t *top);
//4.出栈
datatype PopLinkStack(linkstack_t **ptop);
//5.清空栈
void ClearLinkStack(linkstack_t **ptop);//用二级指针,是因为清空后需要将main函数中的top变为NULL
//6.求栈的长度
int LengthLinkStack(linkstack_t *top);//用一级指针,是因为我只是求长度,不需要修改main函数中top指针的指向
//7.获取栈顶数据,不是出栈,不需要移动main函数中的top,所以用一级指针
datatype GetTopLinkStack(linkstack_t *top);
#endif
相关操作代码
#include<stdio.h>
#include<stdlib.h>
#include "linkstack.h"
//1.创建一个空的栈
void CreateEpLinkStack(linkstack_t **ptop)
{
*ptop=NULL;
}
//2.入栈 data是入栈的数据
//参数上之所以采用二级指针,因为我们要随着入栈添加新的节点作为头,top需要永远指向当前链表的头,
//那么修改main函数中的top,我们采用地址传递
int PushLinkStack(linkstack_t **ptop, datatype data)
//ptop==&top,*ptop==top;
{
linkstack_t *pnew=(linkstack_t *)malloc(sizeof(linkstack_t));
if(pnew==NULL)
{
perror("PushLinkStack\n");
return -1;
}
pnew->data=data;
pnew->next=NULL;
pnew->next=*ptop;
*ptop=pnew;
return 0;
}
//3.判断栈是否为空
int IsEpLinkStack(linkstack_t *top)
{
return top==NULL;
}
//4.出栈
datatype PopLinkStack(linkstack_t **ptop)
{
if(IsEpLinkStack(*ptop))
{
perror("PopLinkStack err\n");
return -1;
}
linkstack_t *pdel=NULL;
pdel=*ptop;
datatype a=pdel->data;
*ptop=pdel->next;
free(pdel);
pdel=NULL;
return a;
}
//5.清空栈
void ClearLinkStack(linkstack_t **ptop)//用二级指针,是因为清空后需要将main函数中的top变为NULL
{
// linkstack_t *pdel=NULL;
// while(*ptop!=NULL)
// {
// pdel=*ptop;
// *ptop=pdel->next;
// free(pdel);
// pdel=NULL;
// }
while (!IsEpLinkStack(*ptop))
{
PopLinkStack(ptop);
}
}
//6.求栈的长度
int LengthLinkStack(linkstack_t *top)//用一级指针,是因为我只是求长度,不需要修改main函数中top指针的指向
{
int i=0;
while (top!=NULL)
{
i++;
top=top->next;
}
return i;
}
//7.获取栈顶数据,不是出栈,不需要移动main函数中的top,所以用一级指针
datatype GetTopLinkStack(linkstack_t *top)
{
if(!IsEpLinkStack(top))
return top->data;
return -1;
}
总结:
顺序栈和链式栈的区别?
1)存储结构不同,顺序栈相当于数组,连续;链式栈 链表 内存不连续
2)顺序栈长度受限制,链式栈不会
队列(queue)
1.概念:
只允许在两端进行插入和删除操作的线性表,在队尾插入,在队头删除
2.特点:
先入先出,后入后出
FIFO LILO
顺序队列
1)逻辑结构:线性结构
2)存储结构:顺序存储
3)操作:
#include <stdio.h>
#include <stdlib.h>
#define N 5
typedef int datatype;
typedef struct
{
datatype data[N];//循环队列的数组
int rear;//存数据端 rear 后面
int front;//取数据端 front 前面
}sequeue_t;
//1.创建一个空的队列
sequeue_t *CreateEmptySequeue();
//2.入列 data代表入列的数据
int InSequeue(sequeue_t *p,datatype data);
//3.判断队列是否为满
int IsFullSequeue(sequeue_t *p);
//4.判断队列是否为空
int IsEmptySequeue(sequeue_t *p);
//5.出列
datatype OutSequeue(sequeue_t *p);
//6.求队列的长度
int LengthSequeue(sequeue_t *p);
//7.清空队列函数
void ClearSequeue(sequeue_t *p);
相关操作代码
#include "sequeue.h"
//1.创建一个空的队列
sequeue_t *CreateEmptySequeue()
{
sequeue_t *p=(sequeue_t *)malloc(sizeof(sequeue_t));
if (p==NULL)
{
perror("CreateEmptySequeue err\n");
return NULL;
}
p->rear=0;
p->front=0;
return p;
}
//3.判断队列是否为满
int IsFullSequeue(sequeue_t *p)
{
return (p->rear+1)%N==p->front;
}
//2.入列 data代表入列的数据
int InSequeue(sequeue_t *p,datatype data)
{
if (IsFullSequeue(p))
{
perror("InSequeue err\n");
return -1;
}
p->data[p->rear]=data;
p->rear=(p->rear+1)%N;
return 0;
}
//4.判断队列是否为空
int IsEmptySequeue(sequeue_t *p)
{
return p->rear==p->front;
}
//5.出列
datatype OutSequeue(sequeue_t *p)
{
if (IsEmptySequeue(p))
{
perror("OutSequeue err\n");
return -1;
}
datatype a=p->data[p->front];
p->front=(p->front+1)%N;
return a;
}
//6.求队列的长度
int LengthSequeue(sequeue_t *p)
{
return (p->rear+N-p->front)%N;
}
//7.清空队列函数
void ClearSequeue(sequeue_t *p)
{
p->rear=p->front;
}
int main(int argc, char const *argv[])
{
sequeue_t *p=CreateEmptySequeue();
for (int i=0;i<4;i++)
InSequeue(p,i);
while (!IsEmptySequeue(p))
{
printf("%d ",OutSequeue(p));
}
printf("\n");
return 0;
}
链式队列
1)逻辑结构:线性结构
2)存储结构:链式存储
3)操作:
#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct node
{
datatype data;//数据域
struct node *next;//指针域
}linkqueue_node_t,*linkqueue_list_t;
//linkqueue_list_t p === linkqueue_node_t *
typedef struct//将队列头指针和尾指针封装到一个结构体里
{
linkqueue_list_t front;//相当于队列的头指针
linkqueue_list_t rear;//相当于队列的尾指针
//有了链表的头指针和尾指针,那么我们就可以操作这个链表
}linkqueue_t;
//1.创建一个空的队列
linkqueue_t *CreateEmptyLinkQueue();
//2.入列 data代表入列的数据
int InLinkQueue(linkqueue_t *p,datatype data);
//3.出列
datatype OutLinkQueue(linkqueue_t *p);
//4.判断队列是否为空
int IsEmptyLinkQueue(linkqueue_t *p);
//5.求队列长度的函数
int LengthLinkQueue(linkqueue_t *p);
//6.清空队列
void ClearLinkQueue(linkqueue_t *p);
相关操作代码
#include "linkqueue.h"
//1.创建一个空的队列
linkqueue_t *CreateEmptyLinkQueue()
{
linkqueue_list_t pnew=(linkqueue_list_t)malloc(sizeof(linkqueue_list_t));
if(pnew==NULL)
{
perror("CreateEmptyLinkQueue err\n");
return NULL;
}
pnew->next=NULL;
linkqueue_t *p=(linkqueue_t *)malloc(sizeof(linkqueue_t));
if(p==NULL)
{
perror("CreateEmptyLinkQueue err\n");
return NULL;
}
p->rear=pnew;
p->front=pnew;
return p;
}
//2.入列 data代表入列的数据
int InLinkQueue(linkqueue_t *p,datatype data)
{
linkqueue_list_t pnew=(linkqueue_list_t)malloc(sizeof(linkqueue_node_t));
if(pnew==NULL)
{
perror("InLinkQueue err\n");
return -1;
}
pnew->data=data;
pnew->next=NULL;
p->rear->next=pnew;
p->rear=pnew;
return 0;
}
//4.判断队列是否为空
int IsEmptyLinkQueue(linkqueue_t *p)
{
return p->front==p->rear;
}
//3.出列
datatype OutLinkQueue(linkqueue_t *p)
{
if (IsEmptyLinkQueue(p))
{
perror("OutLinkQueuev err\n");
return -1;
}
linkqueue_list_t pdel=NULL;
pdel=p->front;
p->front=pdel->next;
free(pdel);
pdel=NULL;
return p->front->data;
}
//5.求队列长度的函数
int LengthLinkQueue(linkqueue_t *p)
{
linkqueue_list_t q=p->front;
int len=0;
while(q->next!=NULL)
{
len++;
q=q->next;
}
}
//6.清空队列
void ClearLinkQueue(linkqueue_t *p)
{
while (!IsEmptyLinkQueue(p))
{
OutLinkQueue(p);
}
}
int main(int argc, char const *argv[])
{
linkqueue_t *p=CreateEmptyLinkQueue();
printf("1\n");
for (int i=0;i<4;i++)
InLinkQueue(p,i);
printf("2\n");
while(!IsEmptyLinkQueue(p))
{
printf("%d ",OutLinkQueue(p));
}
free(p);
return 0;
}