C语言实现队列、栈以及单链表各个操作

队列的特点

队列是一种线性存储结构,其中的数据遵循先进先出(First In First Out)的原则,简称FIFO;

其添加元素在队尾或者队头添加元素。

队列的存与取

初始化:

typedef struct
{
    int data[MAX];  //数据流
    int head;       //头
    int rear;       //尾
    int size;       //队列内容大小
}queue;

//队列初始化
void init_queue(queue *p){
    p->head=0;
    p->rear=0;
    p->size=0;
}

入队(push):

bool push(queue *p, int val)
{
    if (p->size == MAX)    //如果队列已经存满,则报错
    {
        return false;
    }
    p->data[p->rear] = val;    
    p->rear = (p->rear + 1) % MAX;    //尾指针向后移动
    p->size++;    //队列大小增加
}

出队(pop):

int pop(queue *p)
{
    if (p->size == 0)    //为空则报错
    {
        printf("\nqueque is empty!\n");
        return 0;
    }
    int val = p->data[p->head];    //从头指针开始取,因为先进先出
    p->head = (p->head + 1) % MAX;    //移动指针
    p->size--;
    return val;
}

队列中,分别在结构体中定义了两个指针(实际是个记号),一个为头一个位尾,插入时,尾指针向后移动头指针不变,出队时尾指针不变,头指针向后移动;通过%来控制指针的循环移动。

此代码只实现了已知大小的队列基础操作,若想要循环使用还需做修改。

栈的特点

栈也是一个线性存储结构,栈中的元素遵循先进后出(First In Last Out)原则,简称FILO结构;

栈限定只能在栈顶进行插入和删除操作。

栈的存与取

初始化:(栈因为只在栈顶操作,因此可以只需要一个指针)

typedef struct
{
    int data[MAX];
    int fp;
    int size;
}stack;
void init_stack(stack *p){
    p->size=0;
    p->fp=0;
}

入栈(push):

bool push(stack *p,int data){
    if (p->size==MAX)
    {
        printf("FULL");
        return false;
    }
    p->data[p->fp++]=data;
    p->size++;
}

出栈(pop):

int pop(stack *p){
    if (p->size==0)
    {
        printf("\nNULL\n");
        return -1;
    }
    int val=p->data[--p->fp];
    p->size--;
    return val;
}

因为栈的特点,因此比队列相对简单,著名的汉诺塔其实就是在三个栈中进行存取,栈比较符合我们平时对数组的操作(先进后出)。

单链表(有头和无头)

单链表是一种链式存储的数据结构,链表中的数据是以结点来表示的,每个结点的构成:元素+指针(指向后一结点)。

其中有头单链表和无头单链表的区别是,有头单链表会有一个头结点指向第一个结点,而无头单链表只能赋值一个指针指向第一个结点(头结点不是第一个结点),下列为有头单链表的操作。

单链表的插入方式有两种,分别是头插和尾插,顾名思义就是在第一个结点前插入和在末尾插入。

无头单链表的操作

 注意

本人在创建无头单链表时,定义了一个全局静态变量尾指针,是为了方便对单链表进行操作,因此在增删查改时,增加跟删除都要对尾指针进行移动;

嫌麻烦的可以不定义此指针,但是每次在进行尾插时,都需要遍历链表。

下列函数其实就是将尾指针移动到最后一位。

dog *mvtail(dog *p)    //移动尾插的尾指针
{
    while ((p)->next!=NULL)
    {
        (p)=(p)->next;
    }
    tail=(p);
    return tail;
}

定义链表结构
typedef struct dog
{
    int num;
    struct dog *next;
} dog;
static dog *tail;    //定义一个全局静态变量尾指针
创建新结点
dog *creat(int num) // 创建新节点
{
    dog *dg = (dog *)malloc(sizeof(dog));
    dg->num = num;
    dg->next = NULL;
    return dg;
}
头插
void insert_head(dog **p, int num) // 头插
{
    dog *dg = creat(num);
    dg->next = (*p);
    (*p) = dg;
}

有头单链表中,只需用先让新结点指向第一个结点,再用头结点指向新结点。

尾插
void insert_tail(dog **p,int num)   //尾插
{
    if(*p==NULL)    //链表为空,则创建链表
    {
        tail=NULL;
        dog *dg = creat(num);
        (*p)=dg;
        tail=(*p);
        dg->next=NULL;
        return;
    }
    dog *dg = creat(num);
    tail->next=dg;
    dg->next=NULL;
    tail=dg;
}
删除
void myremove(dog **p,int num)    //删除
{
    dog *re=*p;
    dog *pre=NULL;
    if(re->num==num)    //删除位置在头结点
    {
        *p=(*p)->next;
        re->next=NULL;
        free(re);    //删除使用free函数释放内存,因为结点是malloc动态分配的内存
        return;
    }
    while (re->next!=NULL)    
    {
        pre=re;
        re=re->next;
        if(re->num==num)
        {
            pre->next=re->next;
            re->next=NULL;
            free(re);
            return;
        }
    }
    pre->next=NULL;    //走到这一步时,代表删除位置在最后一个结点
    free(re);
}
查找
dog *fount(dog *p, int queen) // 查找
{
    dog *tmp = king->next;
    while ((tmp->num) != queen)
    {
        tmp = tmp->next;
    }
    return tmp;
}
销毁
void destroyed(dog **p) //销毁
{
    dog *del=(*p);
    dog *tmp=NULL;
    while (del)
    {
        tmp=del->next;
        del->next=NULL;
        free(del);
        del=tmp;
    }
    (*p)->next=NULL;
    printf("销毁成功!\n");
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值