C语言单向不循环链表

目录

链表的概念

 1、设计节点类型

2、创建链表 

3、头插法 

 4、尾插法

​ 5、打印链表节点数据

6、头删法 

 7、尾删法

 8、链表节点数据个数

9、指定位置插入

10、指定位置删除

11、链表冒泡排序

12、菜单 

整体代码显示

测试

链表的概念

链表的两种结构

物理结构和逻辑结构

物理 存储单元 上非连续、非顺序的 存储结构,

逻辑上是连续的,他们之间用指针连续起来

链表中每一个元素称为节点,由一系列的节点组成。

每个节点包括两部分,存储数据元素的数据域(data)和存储下一个节点地址的指针域(next)。

如图所示:下图有四个节点,头节点一般不存数据,head为头节点,next为指向下一个节点的

指针(存储下一个节点的地址),单向不循环链表最后一个节点的指针域,指向空(NULL)。

 1、设计节点类型


/**************设计节点类型**************/
typedef struct ListNode
{
    int data;              //数据域
    struct ListNode *next; //地址域
} node_t;

2、创建链表 

申请头节点空间

/********创建链表********/
node_t *CreateList()
{
    node_t *head = (node_t *)malloc(sizeof(node_t)); //申请头节点空间
    if (head == NULL)
    {
        perror("head is null\n"); //如果空间申请失败报错
        return NULL;
    }
    head->data = 0; //头节点数据域不放数据,初始化
    head->next = NULL;

    return head;
}

3、头插法 

/************头插法************/
int InsertHListNode(node_t *head, int newdata)
{
    // 1、判断
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    // 2、申请新节点空间
    node_t *newnode = (node_t *)malloc(sizeof(node_t));
    if (newnode == NULL)
    {
        perror("newnode is null\n");
        return -1;
    }
    // 3、填写数据
    newnode->data = newdata;
    // 4、修改指针
    newnode->next = head->next;
    head->next = newnode; //头节点指向新节点
    return 0;
}

头插法就是在头节点后插入新节点(头节点不放数据所以从头节点后一个位置插入),核心就是 将新节点两条线连接起来

 

 4、尾插法

/************尾插法************/
int InserttListNode(node_t *head, int newdata)
{
    // 1、判断
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    // 2、申请新节点空间
    node_t *newnode = (node_t *)malloc(sizeof(node_t));
    if (newnode == NULL)
    {
        perror("malloc error\n");
        return -1;
    }
    // 3、填写数据
    newnode->data = newdata;
    // 4、找尾
    node_t *temp = head;       //因为头节点不能动所以申请一个中间变量
    while (temp->next != NULL) //当temp->next = NULL时跳出循环
    {
        temp = temp->next;
    }

    // 5、修改指针
    newnode->next = temp->next; //新节点指向最后
    temp->next = newnode;       //新节点接到最后一个节点后
    return 0;
}

尾插法 核心就是找尾,找到尾后修改指针的指向,代码中的指针指向跟图中的指针指向是同一个意思,只是写法不同。

 5、打印链表节点数据

遍历, 循环打印,将链表中的所有的节点数据打印到终端

/*************打印链表***************/
void PrintList(node_t *head)
{
    if (head == NULL)
    {
        perror("There is no data in the linked list, please input it first\n");
        return;
    }

    node_t *temp = head;
    while (temp->next != NULL)
    {
        temp = temp->next; //因为头节点不放数据所以从第二个节点开始
        printf("%d\t", temp->data);
    }
    printf("\n");
}

6、头删法 

/***************头删法*******************/
int DeleteHList(node_t *head)
{
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    //设置一个临时变量
    node_t *temp = head->next;
    head->next = temp->next;
    free(temp); //删除成功释放空间
    temp = NULL;
    return 0;
}

头删法:相对来说是比较简单的,只需要改变一个指针指向。

 7、尾删法

/***************尾删法*******************/
int DeleteTList(node_t *head)
{
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    //设置一个临时变量
    node_t *prev = NULL; //指向尾的前一个节点
    node_t *temp = head;
    //找尾
    while (temp->next->next != NULL)
    {
        temp = temp->next;
    }
    prev = temp;
    temp = temp->next;
    prev->next = NULL;
    free(temp);
    temp = NULL;
    return 0;
}

尾删法:找两个节点先找倒是第二个,在通过倒数第二个找到最后一个,找最后一个是为了释放节点空间。

 8、链表节点数据个数

遍历整个链表,然后返回节点数据个数(因为头节点不放数据所以不包括头节点)

/****************链表的节点元素个数**********************/
int ListLength(node_t *head)
{
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    node_t *temp = head;
    int i = 0;
    while (temp->next != NULL)
    {
        temp = temp->next;
        i++;
    }
    return i;
}

9、指定位置插入

/***************指定位置插入***************/
int InsertLocaList(node_t *head, int newdata, int loca)
{
    //判错
    int len = ListLength(head);
    if (head == NULL || loca <= 0 || loca > len + 1) //插入的位置超范围
    {
        perror("head is null or out of scope\n");
        return -1;
    }
    //申请新节点空间
    node_t *newnode = (node_t *)malloc(sizeof(node_t));
    if (newnode == NULL)
    {
        perror("malloc error\n");
        return -1;
    }
    //填写数据,建立联系
    newnode->data = newdata;
    node_t *temp = head;
    int i = 1;
    while (loca != i)
    {
        temp = temp->next;
        i++;
    }
    newnode->next = temp->next;
    temp->next = newnode;
    return 0;
}

在写之前一定要判断该链表和该位置是否为空,如果都不存在链表和该位置,要插入的节点就接不上了。 

10、指定位置删除

/***************指定位置删除***************/
int DeleteLocaList(node_t *head, int loca)
{
    //判错
    int len = ListLength(head);
    if (head == NULL || loca <= 0 || loca > len) //删除的位置超范围
    {
        perror("head is null or out of scope\n");
        return -1;
    }

    node_t *prev = NULL; //指向尾的前一个节点
    node_t *temp = head;
    int i = 1;
    //找要删除节点的前一个位置
    while (loca != i)
    {
        temp = temp->next;
        i++;
    }
    prev = temp;
    temp = temp->next;
    prev->next = temp->next;
    return 0;
}

11、链表冒泡排序

/************链表冒泡排序*************/
node_t *SortList(node_t *head)
{
    if (head == NULL)
    {
        perror("head is null\n");
        return NULL;
    }
    int len = ListLength(head);
    if (len < 2)
    {
        return head;
    }
    node_t *r, *p, *q; //表示前中后三个节点位置
    r = head;
    for (int i = 0; i < len - 1; i++)
    {
        r = head;
        for (int j = 0; j < len - i - 1; j++)
        {
            p = r->next;
            q = p->next;
            if (q->data < p->data)
            {
                p->next = q->next;
                q->next = p;
                r->next = q;
            }
            r = r->next;
        }
    }
    return head;
}

12、菜单 

void menu(node_t *head)
{
    char ch;
    while (1)
    {
        printf("***************************************\n");
        printf("*****      1.头插                 *****\n");
        printf("*****      2.尾插                 *****\n");
        printf("*****      3.头删                 *****\n");
        printf("*****      4.尾删                 *****\n");
        printf("*****      5.在指定位置插入       *****\n");
        printf("*****      6.在指定位置删除       *****\n");
        printf("*****      7.打印单链表           *****\n");
        printf("*****      8.查看链表中有多少元素 *****\n");
        printf("*****      9.排序                 *****\n");
        printf("*****      0.退出                 *****\n");
        printf("***************************************\n");

        int option = 0, loca = 0, newdata = 0;
        printf("请输入选项:> ");
        scanf("%d", &option);
        switch (option)
        {
        case 9:
            head = SortList(head);
            break;
        case 8:
            printf("链表中有%d个元素\n", ListLength(head));
            break;
        case 7:
            PrintList(head);
            break;
        case 6:
            printf("请输入你要删除的位置:");
            scanf("%d", &loca);
            DeleteLocaList(head, loca);
            break;
        case 5:
            printf("请输入你要插入的位置:");
            scanf("%d", &loca);
            printf("请输入你要插入的元素:");
            scanf("%d", &newdata);
            InsertLocaList(head, newdata, loca);
            break;
        case 4:
            DeleteTList(head);
            break;
        case 3:
            DeleteHList(head);
            break;
        case 2:
            printf("请输入你要插入的元素:");
            scanf("%d", &newdata);
            InserttListNode(head, newdata);
            break;
        case 1:
            printf("请输入你要插入的元素:");
            scanf("%d", &newdata);
            InsertHListNode(head, newdata);
            break;
        case 0:
            return;
        default:
            printf("输入错误\n");
            break;
        }
        printf("是否继续(y/n)\n");
        getchar(); //空吞
        ch = getchar();
        if (ch == 'n' || ch == 'N')
        {
            return;
        }
    }
}

整体代码显示

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

/**************设计节点类型**************/
typedef struct ListNode
{
    int data;              //数据域
    struct ListNode *next; //地址域
} node_t;

node_t *CreateList();                                    //创建链表
int InsertHListNode(node_t *head, int newdata);          //头插法
int InserttListNode(node_t *head, int newdata);          //尾插法
int InsertLocaList(node_t *head, int newdata, int loca); //在指定位置插入
int DeleteHList(node_t *head);                           //头删法
int DeleteTList(node_t *head);                           //尾删法
int DeleteLocaList(node_t *head, int loca);              //在指定位置删除
int ListLength(node_t *head);                            //链表的节点元素个数
void PrintList(node_t *head);                            //打印链表
void menu(node_t *head);                                 //菜单
node_t *SortList(node_t *head);                          //冒泡排序

int main()
{
    node_t *head = CreateList();
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    menu(head);
    return 0;
}

/*****************菜单***********/
void menu(node_t *head)
{
    char ch;
    while (1)
    {
        printf("***************************************\n");
        printf("*****      1.头插                 *****\n");
        printf("*****      2.尾插                 *****\n");
        printf("*****      3.头删                 *****\n");
        printf("*****      4.尾删                 *****\n");
        printf("*****      5.在指定位置插入       *****\n");
        printf("*****      6.在指定位置删除       *****\n");
        printf("*****      7.打印单链表           *****\n");
        printf("*****      8.查看链表中有多少元素 *****\n");
        printf("*****      9.排序                 *****\n");
        printf("*****      0.退出                 *****\n");
        printf("***************************************\n");

        int option = 0, loca = 0, newdata = 0;
        printf("请输入选项:> ");
        scanf("%d", &option);
        switch (option)
        {
        case 9:
            head = SortList(head);
            break;
        case 8:
            printf("链表中有%d个元素\n", ListLength(head));
            break;
        case 7:
            PrintList(head);
            break;
        case 6:
            printf("请输入你要删除的位置:");
            scanf("%d", &loca);
            DeleteLocaList(head, loca);
            break;
        case 5:
            printf("请输入你要插入的位置:");
            scanf("%d", &loca);
            printf("请输入你要插入的元素:");
            scanf("%d", &newdata);
            InsertLocaList(head, newdata, loca);
            break;
        case 4:
            DeleteTList(head);
            break;
        case 3:
            DeleteHList(head);
            break;
        case 2:
            printf("请输入你要插入的元素:");
            scanf("%d", &newdata);
            InserttListNode(head, newdata);
            break;
        case 1:
            printf("请输入你要插入的元素:");
            scanf("%d", &newdata);
            InsertHListNode(head, newdata);
            break;
        case 0:
            return;
        default:
            printf("输入错误\n");
            break;
        }
        printf("是否继续(y/n)\n");
        getchar(); //空吞
        ch = getchar();
        if (ch == 'n' || ch == 'N')
        {
            return;
        }
    }
}

/********创建链表********/
node_t *CreateList()
{
    node_t *head = (node_t *)malloc(sizeof(node_t)); //申请头节点空间
    if (head == NULL)
    {
        perror("head is null\n"); //如果空间申请失败报错
        return NULL;
    }
    head->data = 0; //头节点数据域不放数据,初始化
    head->next = NULL;

    return head;
}

/************头插法************/
int InsertHListNode(node_t *head, int newdata)
{
    // 1、判断
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    // 2、申请新节点空间
    node_t *newnode = (node_t *)malloc(sizeof(node_t));
    if (newnode == NULL)
    {
        perror("newnode is null\n");
        return -1;
    }
    // 3、填写数据
    newnode->data = newdata;
    // 4、修改指针
    newnode->next = head->next;
    head->next = newnode; //头节点指向新节点
    return 0;
}

/************尾插法************/
int InserttListNode(node_t *head, int newdata)
{
    // 1、判断
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    // 2、申请新节点空间
    node_t *newnode = (node_t *)malloc(sizeof(node_t));
    if (newnode == NULL)
    {
        perror("malloc error\n");
        return -1;
    }
    // 3、填写数据
    newnode->data = newdata;
    // 4、找尾
    node_t *temp = head;       //因为头节点不能动所以申请一个中间变量
    while (temp->next != NULL) //当temp->next = NULL时跳出循环
    {
        temp = temp->next;
    }

    // 5、修改指针
    newnode->next = temp->next; //新节点指向最后
    temp->next = newnode;       //新节点接到最后一个节点后
    return 0;
}

/*************打印链表***************/
void PrintList(node_t *head)
{
    if (head == NULL)
    {
        perror("There is no data in the linked list, please input it first\n");
        return;
    }

    node_t *temp = head;
    while (temp->next != NULL)
    {
        temp = temp->next; //因为头节点不放数据所以从第二个节点开始
        printf("%d\t", temp->data);
    }
    printf("\n");
}

/***************头删法*******************/
int DeleteHList(node_t *head)
{
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    //设置一个临时变量
    node_t *temp = head->next;
    head->next = temp->next;
    free(temp); //删除成功释放空间
    temp = NULL;
    return 0;
}

/***************尾删法*******************/
int DeleteTList(node_t *head)
{
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    //设置一个临时变量
    node_t *prev = NULL; //指向尾的前一个节点
    node_t *temp = head;
    //找尾
    while (temp->next->next != NULL)
    {
        temp = temp->next;
    }
    prev = temp;
    temp = temp->next;
    prev->next = NULL;
    free(temp);
    temp = NULL;
    return 0;
}

/****************链表的节点元素个数**********************/
int ListLength(node_t *head)
{
    if (head == NULL)
    {
        perror("head is null\n");
        return -1;
    }
    node_t *temp = head;
    int i = 0;
    while (temp->next != NULL)
    {
        temp = temp->next;
        i++;
    }
    return i;
}

/***************指定位置插入***************/
int InsertLocaList(node_t *head, int newdata, int loca)
{
    //判错
    int len = ListLength(head);
    if (head == NULL || loca <= 0 || loca > len + 1) //插入的位置超范围
    {
        perror("head is null or out of scope\n");
        return -1;
    }
    //申请新节点空间
    node_t *newnode = (node_t *)malloc(sizeof(node_t));
    if (newnode == NULL)
    {
        perror("malloc error\n");
        return -1;
    }
    //填写数据,建立联系
    newnode->data = newdata;
    node_t *temp = head;
    int i = 1;
    while (loca != i)
    {
        temp = temp->next;
        i++;
    }
    newnode->next = temp->next;
    temp->next = newnode;
    return 0;
}

/***************指定位置删除***************/
int DeleteLocaList(node_t *head, int loca)
{
    //判错
    int len = ListLength(head);
    if (head == NULL || loca <= 0 || loca > len) //删除的位置超范围
    {
        perror("head is null or out of scope\n");
        return -1;
    }

    node_t *prev = NULL; //指向尾的前一个节点
    node_t *temp = head;
    int i = 1;
    //找要删除节点的前一个位置
    while (loca != i)
    {
        temp = temp->next;
        i++;
    }
    prev = temp;
    temp = temp->next;
    prev->next = temp->next;
    return 0;
}

/************链表冒泡排序*************/
node_t *SortList(node_t *head)
{
    if (head == NULL)
    {
        perror("head is null\n");
        return NULL;
    }
    int len = ListLength(head);
    if (len < 2)
    {
        return head;
    }
    node_t *r, *p, *q; //表示前中后三个节点位置
    r = head;
    for (int i = 0; i < len - 1; i++)
    {
        r = head;
        for (int j = 0; j < len - i - 1; j++)
        {
            p = r->next;
            q = p->next;
            if (q->data < p->data)
            {
                p->next = q->next;
                q->next = p;
                r->next = q;
            }
            r = r->next;
        }
    }
    return head;
}

测试

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值