嵌入式开发学习--数据结构--顺序表、链表、双向链表、顺序栈、链式栈、循环队列、链式队列(含代码)

顺序表

特点 :内存连续,数组

1)逻辑结构:线性结构

2)存储结构:顺序存储

3)操作:增删改查

函数名命名规则:

下滑线法:create_empty_seqlist

小驼峰法:createEmptySeqList

大驼峰法:CreateEmptySeqList

c 复制代码
#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

操作代码

c 复制代码
#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)操作:增删改查

单向链表

无头单向链表

每个节点的数据域和指针域都有效

有头单向链表

存在一个头节点,头节点的数据域无效,但指针域有效

有头单向链表相关操作

c 复制代码
#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

操作代码

c 复制代码
#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)顺序表查找方便,但是插入和删除麻烦,链表,插入和删除方便,查找麻烦

双向链表

c 复制代码
	
#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);

相关操作

c 复制代码
#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)操作:

c 复制代码
#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 

相关操作代码

c 复制代码
#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)操作:

c 复制代码
#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

相关操作代码

c 复制代码
#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)操作:

c 复制代码
#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);

相关操作代码

c 复制代码
#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)操作:

c 复制代码
#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);

相关操作代码

c 复制代码
#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;
}
相关推荐
AndyFrank4 分钟前
mac crontab 不能使用问题简记
linux·运维·macos
筱源源20 分钟前
Kafka-linux环境部署
linux·kafka
EricWang135831 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??33 分钟前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
小码农<^_^>35 分钟前
优选算法精品课--滑动窗口算法(一)
算法
Mephisto.java37 分钟前
【大数据学习 | kafka高级部分】kafka中的选举机制
大数据·学习·kafka
羊小猪~~37 分钟前
神经网络基础--什么是正向传播??什么是方向传播??
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
算法与编程之美1 小时前
文件的写入与读取
linux·运维·服务器
软工菜鸡1 小时前
预训练语言模型BERT——PaddleNLP中的预训练模型
大数据·人工智能·深度学习·算法·语言模型·自然语言处理·bert
南宫生1 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法