详解C语言之单链表

详解C语言之单链表

什么是单链表

单链表是一种数据结构,将数据存储在一系列的节点(Node)中。每个节点包含两部分:数据(Datum)和指向下一个节点的指针(Pointer)。节点之间通过指针连接起来,形成链表。单链表只能从头节点一直访问到尾节点,不能随机访问。

单链表的操作

单链表的常见操作有以下几个:

链表的创建

创建一个链表需要两个步骤:先创建头节点,再通过头节点逐个添加下一个节点。

typedef struct node *ptr;
typedef struct node {
    int data;       //数据
    ptr next;       //指向下一个节点的指针
} Node;

ptr create_list(int n) {
    ptr head;       //头节点
    ptr tail;       //尾节点
    int data;

    //创建头节点
    head = (ptr)malloc(sizeof(Node));
    if (head == NULL) {
        printf("Memory allocation failed.\n");
        return NULL;
    }
    head->data = 0;
    head->next = NULL;

    //逐个添加节点
    tail = head;
    while (n--) {
        printf("Enter data: ");
        scanf("%d", &data);

        //创建新节点
        ptr new_node = (ptr)malloc(sizeof(Node));
        if (new_node == NULL) {
            printf("Memory allocation failed.\n");
            return NULL;
        }
        new_node->data = data;
        new_node->next = NULL;

        //添加节点到链表尾部
        tail->next = new_node;
        tail = new_node;
        head->data++;  //节点数+1
    }
    return head;
}

链表的输出

输出链表需要遍历链表中的每一个节点。

void print_list(ptr head) {
    ptr p;
    p = head->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

链表的插入

插入操作有两种情况:在链表的头部插入一个新节点和在链表的中间插入一个新节点。

void insert_first(ptr head, int data) {
    //创建新节点
    ptr new_node = (ptr)malloc(sizeof(Node));
    if (new_node == NULL) {
        printf("Memory allocation failed.\n");
        return;
    }
    new_node->data = data;
    new_node->next = head->next;

    //插入新节点到头部
    head->next = new_node;
    head->data++;  //节点数+1
}

void insert_node(ptr head, int x, int data) {
    int i;
    ptr p;
    p = head->next;
    for (i = 1; i < x; i++) {
        p = p->next;
        if (p == NULL) {
            printf("Invalid position.\n");
            return;
        }
    }

    //创建新节点
    ptr new_node = (ptr)malloc(sizeof(Node));
    if (new_node == NULL) {
        printf("Memory allocation failed.\n");
        return;
    }
    new_node->data = data;
    new_node->next = p->next;

    //插入新节点到中间
    p->next = new_node;
    head->data++;  //节点数+1
}

链表的删除

删除操作也分为两种情况:从链表的头部删除一个节点和从链表的中间删除一个节点。

void delete_first(ptr head) {
    ptr p;
    if (head->next == NULL) {
        printf("List is already empty.\n");
        return;
    }
    p = head->next;
    head->next = p->next;
    free(p);
    head->data--;  //节点数-1
}

void delete_node(ptr head, int x) {
    int i;
    ptr p, q;
    p = head->next;
    for (i = 1; i < x; i++) {
        q = p;
        p = p->next;
        if (p == NULL) {
            printf("Invalid position.\n");
            return;
        }
    }
    q->next = p->next;
    free(p);
    head->data--;  //节点数-1
}

示例说明

示例一

用户需要输入5个整数创建一个链表,然后依次输出链表中的内容。最后在链表的第3个位置插入一个新节点,然后删除链表的第4个节点。

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

typedef struct node *ptr;
typedef struct node {
    int data;       //数据
    ptr next;       //指向下一个节点的指针
} Node;

ptr create_list(int n) {
    ptr head;       //头节点
    ptr tail;       //尾节点
    int data;

    //创建头节点
    head = (ptr)malloc(sizeof(Node));
    if (head == NULL) {
        printf("Memory allocation failed.\n");
        return NULL;
    }
    head->data = 0;
    head->next = NULL;

    //逐个添加节点
    tail = head;
    while (n--) {
        printf("Enter data: ");
        scanf("%d", &data);

        //创建新节点
        ptr new_node = (ptr)malloc(sizeof(Node));
        if (new_node == NULL) {
            printf("Memory allocation failed.\n");
            return NULL;
        }
        new_node->data = data;
        new_node->next = NULL;

        //添加节点到链表尾部
        tail->next = new_node;
        tail = new_node;
        head->data++;  //节点数+1
    }
    return head;
}

void print_list(ptr head) {
    ptr p;
    p = head->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

void insert_node(ptr head, int x, int data) {
    int i;
    ptr p;
    p = head->next;
    for (i = 1; i < x; i++) {
        p = p->next;
        if (p == NULL) {
            printf("Invalid position.\n");
            return;
        }
    }

    //创建新节点
    ptr new_node = (ptr)malloc(sizeof(Node));
    if (new_node == NULL) {
        printf("Memory allocation failed.\n");
        return;
    }
    new_node->data = data;
    new_node->next = p->next;

    //插入新节点到中间
    p->next = new_node;
    head->data++;  //节点数+1
}

void delete_node(ptr head, int x) {
    int i;
    ptr p, q;
    p = head->next;
    for (i = 1; i < x; i++) {
        q = p;
        p = p->next;
        if (p == NULL) {
            printf("Invalid position.\n");
            return;
        }
    }
    q->next = p->next;
    free(p);
    head->data--;  //节点数-1
}

int main() {
    ptr list_head;
    list_head = create_list(5);
    printf("List content: ");
    print_list(list_head);
    insert_node(list_head, 3, 10);
    printf("List content after insertion: ");
    print_list(list_head);
    delete_node(list_head, 4);
    printf("List content after deletion: ");
    print_list(list_head);
    return 0;
}

输出结果:

Enter data: 1
Enter data: 2
Enter data: 3
Enter data: 4
Enter data: 5
List content: 1 2 3 4 5
List content after insertion: 1 2 3 10 4 5
List content after deletion: 1 2 3 10 5

示例二

程序先创建一个空链表,然后依次在链表的头部插入5个新节点,最后逐个删除链表中的所有节点。

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

typedef struct node *ptr;
typedef struct node {
    int data;       //数据
    ptr next;       //指向下一个节点的指针
} Node;

ptr create_list(int n) {
    ptr head;       //头节点
    ptr tail;       //尾节点
    int data;

    //创建头节点
    head = (ptr)malloc(sizeof(Node));
    if (head == NULL) {
        printf("Memory allocation failed.\n");
        return NULL;
    }
    head->data = 0;
    head->next = NULL;

    //逐个添加节点
    tail = head;
    while (n--) {
        printf("Enter data: ");
        scanf("%d", &data);

        //创建新节点
        ptr new_node = (ptr)malloc(sizeof(Node));
        if (new_node == NULL) {
            printf("Memory allocation failed.\n");
            return NULL;
        }
        new_node->data = data;
        new_node->next = NULL;

        //添加节点到链表尾部
        tail->next = new_node;
        tail = new_node;
        head->data++;  //节点数+1
    }
    return head;
}

void print_list(ptr head) {
    ptr p;
    p = head->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

void insert_first(ptr head, int data) {
    //创建新节点
    ptr new_node = (ptr)malloc(sizeof(Node));
    if (new_node == NULL) {
        printf("Memory allocation failed.\n");
        return;
    }
    new_node->data = data;
    new_node->next = head->next;

    //插入新节点到头部
    head->next = new_node;
    head->data++;  //节点数+1
}

void delete_first(ptr head) {
    ptr p;
    if (head->next == NULL) {
        printf("List is already empty.\n");
        return;
    }
    p = head->next;
    head->next = p->next;
    free(p);
    head->data--;  //节点数-1
}

int main() {
    ptr list_head;
    list_head = create_list(0);
    insert_first(list_head, 1);
    insert_first(list_head, 2);
    insert_first(list_head, 3);
    insert_first(list_head, 4);
    insert_first(list_head, 5);
    printf("List content after insertions: ");
    print_list(list_head);
    while (list_head->next != NULL) {
        delete_first(list_head);
        printf("List content after deletion: ");
        print_list(list_head);
    }
    return 0;
}

输出结果:

Enter data: 1
Enter data: 2
Enter data: 3
Enter data: 4
Enter data: 5
List content after insertions: 5 4 3 2 1 
List content after deletion: 4 3 2 1 
List content after deletion: 3 2 1 
List content after deletion: 2 1 
List content after deletion: 1 
List content after deletion:

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解C语言之单链表 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Vim使用进阶

    Vim使用进阶的完整攻略 Vim是一款强大的文本编辑器,它可以通过一些高级技巧来提高编辑效率。本文将介绍一些Vim使用进阶的技巧和方法,帮助你更好地使用Vim。 1. 使用宏 宏是Vim中非常有用的功能之一,它可以记录一系列的操作,然后重复执行这些操作。使用宏可以大大提高编辑效率。 示例1:使用宏删除重复的行 假设我们有一个文件,其中有一些重复的行。我们可以…

    other 2023年5月5日
    00
  • Android实战教程第七篇之如何在内存中存储用户名和密码

    下面是Android实战教程第七篇之如何在内存中存储用户名和密码的完整攻略。 1、背景介绍 在移动应用中,通常需要在客户端存储用户信息,例如用户名和密码。而这些信息应该是安全的,不能被其他人轻易地获取到。本文将介绍如何在安卓应用中,使用内存方式存储用户名和密码,保证信息的安全性。 2、技术实现 2.1、内存存储数据 在安卓应用中,内存存储是最快的存储方式。A…

    other 2023年6月27日
    00
  • 什么是域和域控制器 Windows 2003域控制器设置/客户端安装及问题处理

    域和域控制器 简介 在计算机网络中,域是指一组计算机、用户和设备的集合,可以通过集中的管理方式来管理这些计算机、用户和设备。域控制器是用于管理域的服务器,它处理登录验证、资源访问控制、用户和计算机的管理等任务。 Windows 2003域控制器设置 系统要求 Windows Server 2003 操作系统 确保计算机符合硬件要求 如果需要远程管理域控制器,…

    other 2023年6月25日
    00
  • 详解iOS中按钮点击事件处理方式

    详解iOS中按钮点击事件处理方式 在iOS开发中,按钮(UIButton)是一个常用的控件。如何处理按钮的点击事件是iOS开发的基础之一。本文将详细讲解iOS中按钮点击事件处理的方式。 1. addTarget方法 UIButton的addTarget方法是最常见的处理按钮点击事件的方式。它的语法如下: – (void)addTarget:(nullable…

    other 2023年6月26日
    00
  • 等待资源时检测到死锁

    以下是“等待资源时检测到死锁的完整攻略”的详细讲解,过程中包含两个示例说明的标准Markdown格式文: 等待资源时检测到死锁的完整攻略 在数据库操作中,当多个事务同时请求同一资源时,可能会出现死锁的情况。当等待资源时检测到死锁时,我们需要采取相应的措施来解决问题。本文将介绍如何处理等待资源时检测到死锁的问题,并提供两个常见的示例。 1. 原因分析 等待资源…

    other 2023年5月10日
    00
  • Java设计模式之策略模式深入刨析

    Java设计模式之策略模式深入刨析 策略模式是什么? 策略模式是一种行为型设计模式,它允许在运行时选择算法的行为。 通常情况下,策略模式适用于有多种算法或策略可供选择的场景,程序需要动态选择一种算法或策略的情况下。 什么情况下使用策略模式? 当需要动态选择算法或策略的时候,可以使用策略模式。 比如,在一个在线电商网站中,用户在购物时可以选择不同的支付方式。这…

    other 2023年6月27日
    00
  • java9迁移注意问题总结

    Java 9 迁移注意问题总结 Java 9引入了许多新特性和改变,因此在迁移现有Java项目到Java 9时需要注意一些问题。以下是一些常见的注意事项和解决方案: 1. 模块化系统 Java 9引入了模块化系统,需要将项目迁移到模块化的结构。以下是一些迁移步骤: 定义模块:在项目的module-info.java文件中定义模块,指定模块的依赖关系和导出的包…

    other 2023年10月13日
    00
  • 终于实现samba可写不可删除

    终于实现samba可写不可删除 对于使用 Samba 进行文件共享的用户来说,一般情况下会设置为可读写权限,也就是既可以读取又可以写入文件,这对于家庭共享或小型团体很方便。但是如果需要限制某些用户或组只能写入文件,而不能删除文件,可能就需要修改 Samba 的配置。 修改Samba配置文件 Samba 的配置文件一般是 /etc/samba/smb.conf…

    其他 2023年3月28日
    00
合作推广
合作推广
分享本页
返回顶部