C语言基础之单向链表

一、链表的概述

1、单向链表的概述

单向链表是由一个个节点组成,节点没有名字,链表中的每个节点都包含一个存储空间,用于存储数据,以及一个指针,指向下一个节点的位置 达到逻辑上连续。这些节点在内存中是分散存储的,而不是连续存储的。这种分散存储的方式使得链表具有了动态内存分配的能力,可以在运行时根据需要创建和删除节点。

在这里插入图片描述

2、链表和数组优缺点

**静态数组:**int arr[5]; 必须事先确定数组元素的个数,过多浪费,过小溢出,删除插入效率低(需要移动大量数据)

动态数组:不需要事先知道元素个数,在使用中动态申请,删除插入数据效率低(需要移动大量数据)

随机访问效率非常高。我们可以直接通过索引来访问数组中的任意一个元素,而不需要遍历整个数组。

**链表:**不需要事先知道数据个数,在使用中动态申请,插入删除不需要移动数据,在运行时我们只需要改变几个指针就可以在任何位置插入或删除一个元素。(缺点:遍历效率低)

3、单向链表的设计

(1)链表节点设计

#include <stdio.h>

//节点的设置
struct stu
{
    //数据域
    int num;
    char str[128];
    //指针域 连接到的节点
    struct stu *next;
};

int main(int argc, char const *argv[])
{
    //申请空间
    struct stu* data1 = (struct stu*)malloc(sizeof(struct stu));
    struct stu* data2 = (struct stu*)malloc(sizeof(struct stu));
    struct stu* data3 = (struct stu*)malloc(sizeof(struct stu));
    struct stu* data4 = (struct stu*)malloc(sizeof(struct stu));
    struct stu* data5 = (struct stu*)malloc(sizeof(struct stu));
    //初始化数据内容
    data1->num = 10;
    data2->num = 20;
    data3->num = 30;
    data4->num = 40;
    data5->num = 50;
    strcpy(data1->str,"xixi");
    strcpy(data2->str,"haha");
    strcpy(data3->str,"lala");
    strcpy(data4->str,"hehe");
    strcpy(data5->str,"dsds");
    data1->next = NULL;
    data2->next = NULL;
    data3->next = NULL;
    data4->next = NULL;
    data5->next = NULL;

    //定义链表头
    head = data1;//将data1的地址定义为表头
    //连接链表
    data1->next = data2;
    data2->next = data3;
    data3->next = data4;
    data4->next = data5;
    data5->next = NULL; 
    return 0;
}

(2)链表的遍历

    void print_array(struct stu * head)
    {
        //链表的遍历
        struct stu *pb = head;
        while (pb != NULL)
        {
            printf("%d %s\n",pb->num,pb->str);
            pb = pb->next;
        }
    }

4、单向链表的使用

(1)节点的插入

①头部插入

struct stu* head_in(struct stu* head)//头部插入
{
    //为插入的数据申请空间
    struct stu* data = (struct stu*)malloc(sizeof(struct stu));
    //赋值
    data->num = 20;
    strcpy(data->str,"didi");
    data->next = NULL;
    struct stu* pb = head;
    data->next = head;//将原本的头地址赋到新数据的指针域
    head = data;//让新数据的地址作为头地址
    return head;//返回新的头地址
}

②尾部插入

//尾部插入
void tail_in(struct stu* head)
{
    struct stu* data = (struct stu*)malloc(sizeof(struct stu));
    data->num = 80;
    strcpy(data->str,"wei");
    data->next = NULL;
    struct stu* pb = head;
    while (pb->next != NULL)//判断指针域是否为空,为空说明是最后一个数据
    {
        pb = pb->next;
    }
    pb->next = data;//将新数据连接到尾端
}

③有序插入

//有序插入
struct stu* order_in(struct stu* head)
{
    //为插入的数据申请空间
    struct stu* data = (struct stu*)malloc(sizeof(struct stu));
    //赋值
    data->num = 45;
    strcpy(data->str, "youxu");
    data->next = NULL;
    struct stu* pb = head;
    struct stu* fp = head;
    struct stu* ff = head;

    if(data->num < pb->num)//小的在前
    {    
        data->next = head;
        head = data;
    }
    else if(data->num > pb->num)
    {

        while (pb->next != NULL && data->num > pb->num)
        {   
            fp = pb;
            pb = pb->next;
        }
        ff = data;
        ff->next = data->next;

        data = fp;
        data->next = ff;
        ff->next = pb;
    }
    return head;

}

(2)链表的节点查找

struct stu* node(struct stu* head, char *str)
{
    struct stu* pb = head;
    while (strcmp(pb->str, str) != 0 && pb->next != NULL)
    {
        pb = pb->next;
    }
    if(strcmp(pb->str, str) == 0)
    {
        return pb;
    }
    printf("NO\n");
    return NULL;
}

(3)链表节点的删除

//节点删除
struct stu* delet_node(struct stu* head, char *str)
{
    struct stu* pb = head , *pf = head;
    while (strcmp(pb->str, str) != 0 && pb->next != NULL)
    {
        pf = pb;
        pb = pb->next;
    }
    if(strcmp(pb->str, str) == 0)
    {
        if(pb == head)//头节点
        {
            head = head->next;
        }
        else  //中节点
        {
            pf->next = pb->next;
        }
        free(pb);
        return head;
    }
    printf("NO\n");
    return NULL;
}

(4)链表的释放

//释放链表
void free_file(struct stu* head)
{
    struct stu* pb = head;
    while (pb != NULL)
    {
        head = pb->next;
        free(pb);
        pb = head;
    }
    
}

(5)链表的翻转

//链表翻转
struct stu* serversal(struct stu* head)
{
    struct stu* pf = NULL;
    struct stu* pb = head->next;
    head->next = NULL;
    while (pb != NULL)
    {
        pf = pb->next;
        pb->next = head;
        head = pb;
        pb = pf;
    }
    return head;  
}

(6)链表的排序

//链表排序
void sort_file(struct stu* head)
{
    struct stu* p_i = head, *p_j = head; 
    while (p_i->next != NULL) 
    {
        struct stu* p_min = p_i; 
        p_j = p_min->next; 
        while (p_j != NULL) 
        {
            if (p_min->num > p_j->num) 
                p_min = p_j; 
            p_j = p_j->next; 
        }
        if (p_i != p_min) 
        {
            //交换数据
            struct stu tmp = *p_i;
            *p_i = *p_min;
            *p_min = tmp;

            tmp.next = p_i->next;
            p_i->next = p_min->next;
            p_min->next = tmp.next;
        }
        p_i = p_i->next; //i++
    }
}

5、单向链表案例

单向链表存储学生信息

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

//节点的设置
struct stu
{
    //数据域
    int num;
    char str[128];
    //指针域
    struct stu *next;
};
struct stu * head = NULL;

void print_array(struct stu * head);//遍历
struct stu* delet_node(struct stu* head, char *str);//节点删除
struct stu* head_in(struct stu* head, int q,char * w);//头部插入
void free_file(struct stu* head);//释放链表
struct stu* node(struct stu* head, char *str);//节点查找
void sort_file(struct stu* head);//链表排序

void help(void)
{
    printf("*******************************\n");
    printf("*            Help             *\n");
    printf("*            Output           *\n");//输出
    printf("*            Input            *\n");//输入
    printf("*            Delete           *\n");//删除
    printf("*            Query            *\n");//查询
    printf("*            Sort             *\n");//排序
    printf("*            Free             *\n");//关闭
    printf("*******************************\n");
}
int main(int argc, char const *argv[])
{
    help();
    while (1)
    {
        char cmd[128] = "";
        printf("--->Please enter the commed:\n");
        scanf("%s",cmd);
        if(strcmp(cmd, "Help") == 0)
        {
            help();
        }
        else if (strcmp(cmd, "Output") == 0)
        { 
            print_array(head);
        }
        else if (strcmp(cmd, "Input") == 0)
        {
            int q = 0;
            char w[128] = "";
            printf("--->Please input information:\n");
            scanf("%d %s",&q ,w);
            head = head_in(head,q,w);
        }
        else if (strcmp(cmd, "Delete") == 0)//删除
        {
            char data[128] = "";
            printf("--->Please input link\n");
            scanf("%s",data);
            head = delet_node(head,data);
        }
        else if (strcmp(cmd, "Query") == 0)//查询
        {
            struct stu* pf = NULL;
            char data[128] = "";
            printf("--->Please input link\n");
            scanf("%s",data);
            pf = node(head,data);
            if(pf != NULL)
            {
                printf("%d %s\n",pf->num, pf->str);
            }
            
        }
        else if (strcmp(cmd, "Sort") == 0)//排序
        {
            sort_file(head);
        }
        else if (strcmp(cmd, "Free") == 0)//关闭
        {
            free_file(head);
            return 0;
        }
        
    }
    
    return 0;
}
//遍历
void print_array(struct stu * head)
{
    //判断链表是否存在
    if (head == NULL) //不存在
    {
        printf("link not exits\n");
        return;
    }
    //链表的遍历
    struct stu *pb = head;
    while (pb != NULL)
    {
        printf("%d %s\n",pb->num,pb->str);
        pb = pb->next;
    }
}
//节点删除
struct stu* delet_node(struct stu* head, char *str)
{
        if(head == NULL)
    {
        printf("link not exist\n");
        return NULL;
    }
    struct stu* pb = head , *pf = head;
    while (strcmp(pb->str, str) != 0 && pb->next != NULL)
    {
        pf = pb;
        pb = pb->next;
    }
    if(strcmp(pb->str, str) == 0)
    {
        if(pb == head)//头节点
        {
            head = head->next;
        }
        else  //中节点
        {
            pf->next = pb->next;
        }
        free(pb);
        return head;
    }
    printf("NO\n");
    return NULL;
}
//头部插入
struct stu* head_in(struct stu* head,int q, char *w)
{
    struct stu* data = (struct stu*)malloc(sizeof(struct stu));
    data->next = NULL;
    if(head == NULL)
    {
        data->num = q;
        strcpy(data->str,w);
        head = data;
        return head;
    }
    else
    {
        data->num = q;
        strcpy(data->str,w);
        data->next = NULL;
        struct stu* pb = head;
        data->next = head;
        head = data;
        return head;
    }
    
}
//释放链表
void free_file(struct stu* head)
{
    if(head == NULL)
    {
        printf("link not exist\n");
        return;
    }
    struct stu* pb = head;
    while (pb != NULL)
    {
        head = pb->next;
        free(pb);
        pb = head;
    }
    
}
//节点查找
struct stu* node(struct stu* head, char *str)
{
    if(head == NULL)
    {
        printf("link not exist\n");
        return NULL;
    }
    struct stu* pb = head;
    while (strcmp(pb->str, str) != 0 && pb->next != NULL)
    {
        pb = pb->next;
    }
    if(strcmp(pb->str, str) == 0)
    {
        return pb;
    }
    printf("NO\n");
    return NULL;
}
//链表排序
void sort_file(struct stu* head)
{
    if(head == NULL)
    {
        printf("link not exist\n");
        return;
    }
    struct stu* p_i = head, *p_j = head; 
    while (p_i->next != NULL) 
    {
        struct stu* p_min = p_i; 
        p_j = p_min->next; 
        while (p_j != NULL) 
        {
            if (p_min->num > p_j->num) 
                p_min = p_j; 
            p_j = p_j->next; 
        }
        if (p_i != p_min) 
        {
            //交换数据
            struct stu tmp = *p_i;
            *p_i = *p_min;
            *p_min = tmp;

            tmp.next = p_i->next;
            p_i->next = p_min->next;
            p_min->next = tmp.next;
        }
        p_i = p_i->next; //i++
    }
}

6、如有错误欢迎指正

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C语言中,使用malloc函数可以动态地分配内存空间。下面是一个示例,演示了如何使用malloc函数来分配空间并创建一个单向链表: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构体 typedef struct Node { int data; struct Node* next; } Node; // 创建链表节点 Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); if (newNode == NULL) { printf("内存分配失败\n"); return NULL; } newNode->data = data; newNode->next = NULL; return newNode; } // 初始化链表 Node* initList() { Node* head = createNode(0); // 创建头节点 if (head == NULL) { return NULL; } return head; } // 在链表末尾插入节点 void insertNode(Node* head, int data) { Node* newNode = createNode(data); if (newNode == NULL) { return; } Node* temp = head; while (temp->next != NULL) { temp = temp->next; } temp->next = newNode; } // 打印链表 void printList(Node* head) { Node* temp = head->next; // 跳过头节点 while (temp != NULL) { printf("%d ", temp->data); temp = temp->next; } printf("\n"); } // 释放链表内存 void freeList(Node* head) { Node* temp = head; while (temp != NULL) { Node* nextNode = temp->next; free(temp); temp = nextNode; } } int main() { Node* head = initList(); // 初始化链表 if (head == NULL) { return 0; } insertNode(head, 1); // 在链表末尾插入节点 insertNode(head, 2); insertNode(head, 3); printList(head); // 打印链表 freeList(head); // 释放链表内存 return 0; } ``` 这段代码演示了如何使用malloc函数来分配空间并创建一个单向链表。首先,我们定义了一个链表节点结构体,包含数据和指向下一个节点的指针。然后,我们实现了创建节点、初始化链表、插入节点、打印链表和释放链表内存的函数。在主函数中,我们初始化链表,插入节点,打印链表,最后释放链表内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值