数据结构单向循环链表的Linux Ubuntu 下的C语言实现

       大家好,我是练习编程时长两年半的昆工第一ikun,今天咋们来说一下线性链表和单向循环链表,这个是个很基础的链表,咋们来分成线性链表和单向循环链表来说。

一、线性链表

1.逻辑结构:线性结构

2.存储结构:链式存储,每个元素的地址空间不是连续

优点:链表能够解决顺序表中资源空间浪费的问题以及空间不足的问题

缺点:链表的查找和修改元素效率低

3.链表相关操作算法:

①创建链表的头节

②判断链表是否是空链表

③计算表长

④从表头插入数据

⑤按位置插入数据

⑥按位置删除数据

⑦按数据删除

⑧按位置查找元素

⑨按数据查找元素

⑩清空链表,删除链表

4.链表节点相关结构体

typedef int data_t;
typedef struct linklist
{
    data_t data; //数据域
    struct linklist *next; //指针域
​
}LinkList;

5.linklist.h头文件代码

#ifndef _LINKLIST_
#define _LINKLIST_

typedef int data_t;
typedef struct linklist 
{
    data_t data;
    struct linklist *next;

}LinkList;

LinkList *Create_Linklist(); //创建链表的表头

int Linklist_Is_Empty(LinkList *head); //判空

int Linklist_Size(LinkList *head); //计算表长

void Linklist_Insert_Head(LinkList *head, data_t data); //从表头插入数据

void Linklist_Insert_Pos(LinkList *head, int Pos, data_t data); //按位置插入数据

void Linklist_Delete_Pos(LinkList *head, int pos); //按位置删除数据

void Linklist_Delete_Data(LinkList *head, data_t data); //按数据删除

void Linklist_Find__Pos(LinkList *head, int pos); //按位置查找 

void Linklist_Find_Data(LinkList *head, data_t data); //按数据查找

void Linklist_Eidt__Pos(LinkList *head, int pos, data_t data); //按位置修改

void Linklst_Empty(LinkList *head); //清空链表

void Linklist_Delete(LinkList **head);//删除链表

void Linklist_Exchange(LinkList *head); //将表逆序

void Linklist_Show(LinkList *head); //打印链表

#endif

6.linklist.c函数内容实现代码

#include <stdio.h>
#include <stdlib.h>
#include "linklist.h"

//*********************创建链表的头节点*****************
LinkList *Create_Linklist()
{
    LinkList *head = (LinkList *)malloc(sizeof(LinkList)); //给链表在堆区开辟空间
    if(head == NULL){
        printf("创建失败!\n");
        return NULL;
    }
    head->data = -1;
    head->next = NULL;
    return head;
}

//*******************判空*****************
int Linklist_Is_Empty(LinkList *head)
{
    if(head->next == NULL){
        return 1;
    }
    else{
        return 0;
    }
}

//*********************计算表长*****************
int Linklist_Size(LinkList *head) 
{
    int len = 0;
    LinkList *p = head->next;
    while(p != NULL){
        len++;
        p = p->next;
    }
    return len;
}

//*************************从表头插入数据********************************
void Linklist_Insert_Head(LinkList *head, data_t data)
{
    LinkList *new = (LinkList *)malloc(sizeof(LinkList)); //创建新的节点
    if(NULL == new){
        printf("创建失败!\n");
        return;
    }
    new->data = data;     //给新节点赋值
    new->next = NULL;

    new->next = head->next;   //将新节点与头节点链接
    head->next = new;         
    return;
}

//***********************按位置插入数据**************************
void Linklist_Insert_Pos(LinkList *head, int pos, data_t data)
{
    if(pos < 0 || pos > Linklist_Size(head)-1){      //判断位置是否合法
        printf("位置错误!\n");
    }

    LinkList *new = (LinkList *)malloc(sizeof(LinkList)); //创建新的节点
    if(NULL == new){
        printf("创建失败!\n");
        return;
    }
    new->data = data;
    new->next = NULL;

    LinkList *p = head->next;  //找到插入位置的上一个节点的地址
    while(pos--){
        p = p->next;
    }
    new->next = p->next;
    p->next = new;
    return;
}

//**************************按位置删除数据***************************
void Linklist_Delete_Pos(LinkList *head, int pos)
{
    if(Linklist_Is_Empty(head) == 1){
        printf("该表为空!\n");
        return;
    }
    if(pos < 0 || pos > Linklist_Size(head)-1){      //判断位置是否合法
        printf("位置错误!\n");
    }

    LinkList *p = head;  //找到删除位置节点的地址
    LinkList *q = NULL;
    while(pos--){
        p = p->next;
    }
    q = p->next;
    p->next = q->next;
    free(q);
    q = NULL;
    return;
}

//**************************按数据删除***************************
void Linklist_Delete_Data(LinkList *head, data_t data)
{
    if(Linklist_Is_Empty(head) == 1){
        printf("该表为空!\n");
        return;
    }
    LinkList *w = head;  //找到删除位置节点的地址
    int ret = Linklist_Size(head), i = 0;
    while(i < ret){
        w = w->next;
        if((w->data) == data){
            int pos = i;           //确定删除数据的位置
            Linklist_Delete_Pos(head, pos);        
            break;
        }
        i++;
    }
    return;
}

//************************按位置查找**************************
void Linklist_Find__Pos(LinkList *head, int pos)
{
    if(Linklist_Is_Empty(head) == 1){
        printf("该表为空!\n");
        return;
    }
    if(pos < 0 || pos > Linklist_Size(head)-1){      //判断位置是否合法
        printf("位置错误!\n");
    }

    LinkList *p = head;
    while(pos--){
        p = p->next;
    }
    printf("该值为:%d\n", p->data);
    return;
}

//***************************按数据查找***************************
void Linklist_Find_Data(LinkList *head, data_t data)
{
    if(Linklist_Is_Empty(head) == 1){
        printf("该表为空!\n");
        return;
    }
    LinkList *p = head;
    int ret = Linklist_Size(head), i = 0, pos;
    while(i < ret){
        p = p->next;
        if((p->data) == data){
            pos = i;              //确定数据的位置
            break;
        }
        i++;
    }
    printf("该值的位置为:%d\n", pos);
    return;
}

//****************************按位置修改*************************
void Linklist_Eidt__Pos(LinkList *head, int pos, data_t data)
{
    if(Linklist_Is_Empty(head) == 1){
        printf("该表为空!\n");
        return;
    }
    if(pos < 0 || pos > Linklist_Size(head)-1){      //判断位置是否合法
        printf("位置错误!\n");
        return;
    }

    LinkList *p = head->next;
    while(pos--){
        p = p->next;
    }
    p->data = data;
    return;
}

//************************清空链表***********************
void Linklst_Empty(LinkList *head)
{
    LinkList *p = head;
    LinkList *q = NULL;
    int len = Linklist_Size(head);
    len--;
    while(len--){
        q = p->next;
        p->next = q->next;
        free(q);
        q = NULL;
    }
    q = head->next;
    free(q);
    q = NULL;
    head->next = NULL;
    return;
}

//************************删除链表***********************
void Linklist_Delete(LinkList **head)
{
    Linklst_Empty(*head);
    free(*head);
    *head = NULL;
    return;
}

//***********************链表逆序************************
void Linklist_Exchange(LinkList *head)
{
    LinkList *p = head->next;
    LinkList *q = NULL;
    head->next = NULL;

    while(p != NULL){
        q = p->next;
        p->next = head->next;
        head->next = p;
        p = q;
    }
return;

}

//************************打印链表***********************
void Linklist_Show(LinkList *head)
{
    LinkList *p = head->next;
    while(p != NULL){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
    return;
}

7.main.c主函数代码

       由于坤坤没有太多时间,而且主函数的菜单列表也比较简单,所以坤坤没有写出主菜单,只是把函数功能实现了一遍,希望大家多多包涵。

#include <stdio.h>
#include "linklist.h"

int main(int argc, char *argv[])
{
     LinkList *head = Create_Linklist();

    int n = 10;
    while(n--)
    {
        Linklist_Insert_Head(head, n);
    }

    Linklist_Show(head);
    int len =  Linklist_Size(head);
    printf("len = %d\n", len);

    Linklist_Insert_Pos(head, 5, 100);
    Linklist_Show(head);

    Linklist_Delete_Pos(head, 8);
    Linklist_Show(head);

    Linklist_Delete_Data(head, 3);
    Linklist_Show(head);
    
    Linklist_Find__Pos(head, 4); 

    Linklist_Find_Data(head, 100);

    Linklist_Eidt__Pos(head, 8, 999);
    Linklist_Show(head);

/*  Linklst_Empty(head);
    Linklist_Show(head); 

    Linklist_Delete(&head);
    Linklist_Show(head); */

    Linklist_Exchange(head);
    Linklist_Show(head);

    return 0;
} 

        现在,有一部分练习时长超过两年半的ikun就要问了,线性链表不能从结尾遍历回来,我心里不舒服,用着也不好用,那么下面我就来给大家介绍单向循环链表。

二、单向循环链表

      单向循环链表与线性链表大体相同,只是把首尾连接了起来,请看代码。

1.clinklist.h头文件代码

#ifndef _LINKLIST_
#define _LINKLIST_

typedef int data_t;
typedef struct clinklist 
{
    data_t data;
    struct clinklist *next;

}ClinkList;

ClinkList *Create_Clinklist(); //创建链表

void Clinklist_Insert_Head(ClinkList *head, data_t data); //头插法插入链表

void Clinklist_Ab_A(ClinkList *A, ClinkList *B);  //将单向循环链表AB合成一个链表A

void Clinklist_Show(ClinkList *head);  //打印链表

void Clinklist_Delete_Pos(ClinkList *head, int pos);  //任意位置删除数据

void Clinklist_Insert_Pos(ClinkList *head, int pos, data_t data); //从任意位置插入数据

int Clinklist_Size(ClinkList *head); //判断链表长度

#endif

2.clinklist.c函数功能实现代码

#include <stdio.h>
#include <stdlib.h>
#include "clinklist.h"

//*********************创建链表的头节点*****************
ClinkList *Create_Clinklist()
{
    ClinkList *head = (ClinkList *)malloc(sizeof(ClinkList)); //给链表在堆区开辟空间
    if(head == NULL){
        printf("创建失败!\n");
        return NULL;
    }
    head->data = -1;
    head->next = head;
    return head;
}

//*************************判断链表长度***************************
int Clinklist_Size(ClinkList *head)
{
    ClinkList *p = head;
    int len = 0;
    while(p->next != head){
        p = p->next;
        len++;
    }
    return len;
}

//*************************从表头插入数据********************************
void Clinklist_Insert_Head(ClinkList *head, data_t data)
{
    ClinkList *new = (ClinkList *)malloc(sizeof(ClinkList)); //创建新的节点
    if(NULL == new){
        printf("创建失败!\n");
        return;
    }
    new->data = data;     //给新节点赋值
    new->next = NULL;

    new->next = head->next;   //将新节点与头节点链接
    head->next = new;         
    return;
}

//************************从任意位置插入数据*************************
void Clinklist_Insert_Pos(ClinkList *head, int pos, data_t data)
{
    if(pos < 0 || pos > Clinklist_Size(head)-1){        //判断输入的位置是否合法
        printf("该位置不存在!!!\n");
        return;
    }
    ClinkList *new = (ClinkList *)malloc(sizeof(ClinkList)); //创建新的节点
    if(NULL == new){
        printf("创建失败!\n");
        return;
    }
    new->data = data;     //给新节点赋值
    new->next = NULL;
    
    ClinkList *p = head->next;
    while(pos--){
        p = p->next;
    }
    new->next = p->next;
    p->next = new;
    return;
}

//*********************按任意位置删除链表**********************
void Clinklist_Delete_Pos(ClinkList *head, int pos)
{
    if(pos < 0 || pos > Clinklist_Size(head)-1){        //判断输入的位置是否合法
        printf("该位置不存在!!!\n");
        return;
    }
    ClinkList *p = head;
    ClinkList *q = NULL;
    while(pos--){
        p = p->next;
    }
    q = p->next;
    p->next = q->next;
    free(q);
    q = NULL;
    return;
}

//************************将两个单向循环链表组合成一个********************
void Clinklist_Ab_A(ClinkList *A, ClinkList *B)
{
    ClinkList *p = A->next;
    ClinkList *q = B->next;
    
    while(p->next != A){
        p = p->next;
    }
    while(q->next != B){
        q = q->next;
    }
    p->next = q->next->next;
    q->next = A;
    B = NULL;
    return;
}

//************************打印链表*******************************
void Clinklist_Show(ClinkList *head)
{
    ClinkList *p = head->next;
    while(p != head){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
    return;
}

3.main.c主函数代码

#include <stdio.h>
#include "clinklist.h"

int main(int argc, char *argv[])
{ 
    ClinkList *A = Create_Clinklist();

    int n = 10;
    while(n--)
    {
        Clinklist_Insert_Head(A, n);
    }

    Clinklist_Show(A);
    
    ClinkList *B = Create_Clinklist();

    n = 10;
    while(n--)
    {
        Clinklist_Insert_Head(B, n);
    }
    Clinklist_Show(B);

    Clinklist_Ab_A(A, B);
    Clinklist_Show(A);


Clinklist_Delete_Pos(A, 5);  //任意位置删除数据
Clinklist_Show(A);

Clinklist_Insert_Pos(A, 2, 999); //从任意位置插入数据
Clinklist_Show(A);

int len = Clinklist_Size(A); //判断链表长度
 printf("%d\n", len);
 
    return 0;
} 

        好了,今天的分享结束了,今天的链表是单向奔赴,那有没有双向奔赴的链表呢?当然有,坤坤明天就告诉你,我是练习编程时长两年半的个人练习生昆工第一ikun,我们明天见。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值