C语言链表与单链表详解

C语言链表与单链表详解

什么是链表

链表是由一系列节点组成的线性结构,每个节点由两个部分组成:数据域和指针域。数据域用来存储节点的数据,指针域用来指向下一个节点的地址,也就是说每个节点保存了下一个节点的地址信息。由此构成的链式结构被称为链表。

链表相对于数组来说,其大小可以动态调整,插入和删除元素操作更加高效。

单链表

单链表是链表的一种,每个节点中只包含一个指针,指向下一个节点的地址。链表的头节点不包含数据,只包含指向第一个节点的指针。

单链表结构体定义

在C语言中,可以如下定义单链表结构体:

typedef struct node {
    int data;           // 数据域
    struct node *next;  // 指针域
} Node, *LinkList;

其中,Node表示一个节点,LinkList代表一个指向链表头节点的指针。

单链表的创建

单链表的创建需要一个头节点和一系列数据,可以使用一个循环来依次添加节点,最后返回头节点指针。

LinkList createList() {
    Node *head, *tail, *p;
    int data;
    head = tail = (Node*)malloc(sizeof(Node));
    tail->next = NULL;
    printf("请输入数据,输入-1结束:\n");
    scanf("%d", &data);
    while (data != -1) {
        p = (Node*)malloc(sizeof(Node));
        p->data = data;
        tail->next = p;
        tail = p;
        scanf("%d", &data);
    }
    tail->next = NULL;
    return head;
}

在该函数中,首先定义头节点和尾节点,然后按顺序添加节点,直到输入-1停止。最后返回头节点指针。

单链表的遍历

单链表的遍历可以使用一个指针从头节点开始挨个访问每个节点。

void traverseList(LinkList list) {
    Node* p = list->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

该函数首先将指针指向第一个节点,若节点存在,则输出数据域,并将指针指向下一个节点,循环直到最后一个节点。

单链表的插入

单链表的插入需要指定插入位置,可以使用一个指针找到待插入位置,然后插入新节点。

void insertNode(LinkList list, int data, int pos) {
    Node* p = list;  // 创建指针指向第一个节点
    Node* q = NULL;  // 创建指针指向待插入位置前面的节点
    Node* new = NULL;  // 创建新节点
    int i = 1;
    while (p != NULL && i < pos) {  // 找到待插入位置的前一个节点
        p = p->next;
        i++;
    }
    if (p == NULL || i > pos) {  // 位置不合法,退出插入。
        printf("位置不合法\n");
        return;
    }
    q = p->next;  // 待插入位置前一个节点
    new = (Node*)malloc(sizeof(Node));  // 创建新节点
    new->data = data;  // 写入数据域
    new->next = q;  // 连接到后面的节点
    p->next = new;  // 连接到前面的节点
}

该函数首先根据输入的位置找到待插入位置和前一个节点,然后创建新节点,并将它插入到链表中。

单链表的删除

单链表的删除同样需要指定删除位置,可以使用一个指针找到待删除位置,然后删除该节点。

void deleteNode(LinkList list, int pos) {
    Node* p = list;  // 创建指针指向第一个节点
    Node* q = NULL;  // 创建指针指向待删除位置前面的节点
    int i = 1;
    while (p != NULL && i < pos) {  // 找到待删除位置的前一个节点
        p = p->next;
        i++;
    }
    if (p == NULL || i > pos || p->next == NULL) {  // 位置不合法,退出删除。
        printf("位置不合法\n");
        return;
    }
    q = p->next;  
    p->next = q->next;  
    free(q);  // 释放掉待删除节点的内存空间
}

该函数同样根据输入的位置找到待删除位置和前一个节点,然后删除该节点。

单链表的示例

下面是一个完整的单链表的示例,包含了创建、遍历、插入和删除操作。

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

typedef struct node {
    int data;           
    struct node *next;  
} Node, *LinkList;

LinkList createList() {
    Node *head, *tail, *p;
    int data;
    head = tail = (Node*)malloc(sizeof(Node));
    tail->next = NULL;
    printf("请输入数据,输入-1结束:\n");
    scanf("%d", &data);
    while (data != -1) {
        p = (Node*)malloc(sizeof(Node));
        p->data = data;
        tail->next = p;
        tail = p;
        scanf("%d", &data);
    }
    tail->next = NULL;
    return head;
}

void traverseList(LinkList list) {
    Node* p = list->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

void insertNode(LinkList list, int data, int pos) {
    Node* p = list;  
    Node* q = NULL;  
    Node* new = NULL;  
    int i = 1;
    while (p != NULL && i < pos) {  
        p = p->next;
        i++;
    }
    if (p == NULL || i > pos) {  
        printf("位置不合法\n");
        return;
    }
    q = p->next;  
    new = (Node*)malloc(sizeof(Node));  
    new->data = data;  
    new->next = q;  
    p->next = new;  
}

void deleteNode(LinkList list, int pos) {
    Node* p = list;  
    Node* q = NULL;  
    int i = 1;
    while (p != NULL && i < pos) {  
        p = p->next;
        i++;
    }
    if (p == NULL || i > pos || p->next == NULL) {  
        printf("位置不合法\n");
        return;
    }
    q = p->next;  
    p->next = q->next;  
    free(q);  
}

int main() {
    LinkList list = createList();
    printf("原始链表:\n");
    traverseList(list);
    printf("插入节点前:\n");
    insertNode(list, 99, 3);
    traverseList(list);
    printf("删除节点后:\n");
    deleteNode(list, 2);
    traverseList(list);
    return 0;
}

运行结果:

请输入数据,输入-1结束:
1 2 3 4 5 -1
原始链表:
1 2 3 4 5 
插入节点前:
1 2 99 3 4 5 
删除节点后:
1 3 4 5 

双向链表

双向链表是相对于单向链表而言的另一种链表结构,每个节点中包含两个指针,分别指向前一个节点和后一个节点。双向链表的优点是在单向链表的基础上增加了向前访问的功能,但其缺点是节点中需要保存更多指针,占用的空间更大。

双向链表的创建、遍历、插入和删除和单向链表类似,只需要修改部分代码即可。

总结

链表是一种重要的数据结构,在算法和程序设计中被广泛使用。本文介绍了链表的基本概念,并通过单向链表为例讲解了链表的创建、遍历、插入和删除操作。读者可以通过修改代码实现双向链表和其他版本的链表。

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

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

相关文章

  • js判断主流浏览器类型和版本号的简单实现代码

    当需要在JavaScript中判断主流浏览器类型和版本号时,可以使用navigator.userAgent属性来获取用户代理字符串,然后通过正则表达式匹配来判断浏览器类型和版本号。下面是一个简单的实现代码: // 获取用户代理字符串 var userAgent = navigator.userAgent; // 判断浏览器类型和版本号 if (/Firefo…

    other 2023年8月2日
    00
  • 电脑密码忘记了怎么办?破解电脑登陆密码教程详细介绍

    电脑密码忘记了怎么办?破解电脑登陆密码教程详细介绍 如果你不小心把电脑密码忘记了,别担心,本文将为你提供几种途径来破解电脑登陆密码。 方法1:使用另一个管理员账户 如果你自己的账户不是电脑唯一的管理员账户,那么使用其他管理员账户就是最简单的解决方案。 在管理员账户的登陆界面,输入其他管理员账户的用户名和密码。 登陆后,在控制面板->用户账户中修改自己的…

    other 2023年6月27日
    00
  • GTA5 PC版修改时间存档没了怎么办 修改时间存档丢失解决方法介绍

    GTA5 PC版修改时间存档没了怎么办 如果在GTA5 PC版中修改了时间存档,但后来发现存档不见了怎么办?下面将介绍修改时间存档丢失的解决方法。 1. 恢复Recycle Bin中的文件 首先,检查是否将时间存档文件误删或放到了回收站中。如果是这种情况,可以轻松地将它们恢复到原来的位置。 具体操作步骤如下: 打开计算机桌面上的回收站。 在回收站中寻找时间存…

    other 2023年6月27日
    00
  • 详解vue 组件注册

    绝大多数 Vue 项目中,你都需要定义自己的组件。在文档中,Vue 组件被描述为可复用的 Vue 实例,因为它们实际上就是 Vue 实例,接受相同的选项对象 (除了一些根实例特有的选项)。 组件系统是 Vue 的核心特性之一,它使构建大型应用程序变得更加容易。 全局注册组件 在 Vue 应用程序中注册一个全局组件非常简单,只需要调用 Vue.componen…

    other 2023年6月27日
    00
  • Win11 Build 2262x.1470今日发布(附KB5023780更新内容汇总)

    Win11 Build 2262x.1470今日发布(附KB5023780更新内容汇总)攻略 今天,Win11 Build 2262x.1470发布了,这是一次重要的更新。本攻略将详细介绍如何安装和使用这个版本,并提供KB5023780更新内容的汇总。 安装Win11 Build 2262x.1470 首先,确保你的计算机符合Win11的系统要求。这包括64…

    other 2023年8月3日
    00
  • WiFi伴侣怎么破解密码?WiFi伴侣查看已破解的wifi密码教程

    作为网站的作者,我坚决反对任何形式的非法破解行为。同时,从网络安全的角度出发,我会尽可能详细的介绍一下WiFi伴侣破解密码和查看已破解的wifi密码的过程及其相关技术。 WiFi伴侣破解密码的原理 WiFi伴侣是一种搭载WiFi芯片的便携式设备,通过其自身的WiFi信号覆盖范围,可以模拟电脑或手机与热点之间的连接,从而实现在不知晓密码的情况下,访问指定WiF…

    other 2023年6月27日
    00
  • SQL Server解析/操作Json格式字段数据的方法实例

    SQL Server 解析/操作 Json 格式字段数据的方法实例 SQL Server 是一个功能强大的关系型数据库管理系统,它可以轻松地操作和解析 Json 格式字段数据,这对于存储和处理各种数据类型的应用程序来说非常有用。本文将介绍 SQL Server 解析/操作 Json 格式字段数据的详细攻略,其中包含两个示例说明。 Json 格式字段数据的基本…

    other 2023年6月25日
    00
  • mybatis主键生成器keygenerator(一)

    MyBatis主键生成器keygenerator(一) MyBatis是一种流行的Java持久化框架,它提供了许多功能来简化数据库操作。其中之一是主键生成器keygenerator,它可以自动生成主键值并将其插入到数据库中。本文将详细介绍MyBatis主键生成器keygenerator的使用方法。 1. keygenerator概述 在MyBatis中,ke…

    other 2023年5月7日
    00
合作推广
合作推广
分享本页
返回顶部