C语言数据结构之单向链表详解分析

yizhihongxing

C语言数据结构之单向链表详解分析

什么是单向链表?

单向链表是一种常见的数据结构,它由一系列节点(或称单元)组成,每个节点都包含两个数据域:数据和指针。其中,数据用于存储具体的数据信息,指针则用于指向下一个节点。这样,一个链表就可以看做是由一个一个节点链接而成的数据结构。而单向链表中的指针只能指向下一个节点,因此被称为单向链表。

如何使用单向链表?

单向链表通常用于需要频繁插入、删除节点的场景,因为这种情况下使用数组等静态数据结构会导致效率低下。另外,链表还可以根据需求来灵活扩充大小,可以节省空间。

单向链表的实现

单向链表的实现主要包括链表的初始化、节点的插入、节点的删除、查找节点等功能。

链表的初始化

初始化需定义一个链表头结点,头节点的作用主要为了方便链表中节点的插入、删除等操作。

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

LinkList InitList() {
    LinkList head = (LinkList)malloc(sizeof(Node)); // 动态分配头结点的内存空间
    head->next = NULL;
    return head; // 返回头结点
}

节点的插入

节点的插入需要根据插入位置创建新节点,然后将其连接到链表中。

void InsertNode(LinkList head, int pos, int elem) {
    Node *p = head;
    for (int i = 1; i < pos; i++) {
        if (p == NULL) return;
        p = p->next; // 找到需要插入的位置
    }
    Node *newNode = (Node *)malloc(sizeof(Node)); // 动态分配一个新节点
    newNode->data = elem;
    newNode->next = p->next; // 将新节点插入到链表中
    p->next = newNode;
}

节点的删除

删除节点同样需要找到节点位置,然后将其从链表中删除。

bool DeleteNode(LinkList head, int pos) {
    Node *p = head;
    for (int i = 1; i < pos; i++) {
        if (p == NULL) return false;
        p = p->next; // 找到需要删除的位置
    }
    if (p == NULL || p->next == NULL) return false;
    Node *temp = p->next; // 将节点从链表中删除
    p->next = temp->next;
    free(temp);
    return true;
}

查找节点

查找节点需要遍历整个链表,直到找到目标节点。

Node *GetNode(LinkList head, int pos) {
    Node *p = head;
    for (int i = 1; i <= pos; i++) {
        if (p == NULL || p->next == NULL) return NULL;
        p = p->next; // 遍历链表,直到找到目标节点
    }
    return p;
}

示例

示例1

现在我们需要用单向链表实现一个存储10个元素的列表,列表中元素分别为1, 3, 5,..., 19。可以通过以下方式实现:

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

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

LinkList InitList() {
    LinkList head = (LinkList)malloc(sizeof(Node)); // 动态分配头结点的内存空间
    head->next = NULL;
    return head; // 返回头结点
}

void InsertNode(LinkList head, int pos, int elem) {
    Node *p = head;
    for (int i = 1; i < pos; i++) {
        if (p == NULL) return;
        p = p->next; // 找到需要插入的位置
    }
    Node *newNode = (Node *)malloc(sizeof(Node)); // 动态分配一个新节点
    newNode->data = elem;
    newNode->next = p->next; // 将新节点插入到链表中
    p->next = newNode;
}

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

int main() {
    LinkList head = InitList(); // 初始化链表
    for (int i = 1; i <= 10; i++) {
        InsertNode(head, i, 2 * i - 1); // 插入节点
    }
    PrintList(head); // 输出链表
    return 0;
}

输出结果:

1 3 5 7 9 11 13 15 17 19

示例2

现在我们需要实现一个存储学生信息的单向链表。每个学生信息包含学号和姓名两个字段。可以通过以下方式实现:

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

typedef struct student {
    int no; // 学号
    char name[50]; // 姓名
    struct student *next; // 指针域
} Student, *LinkList; 

LinkList InitList() {
    LinkList head = (LinkList)malloc(sizeof(Student)); // 动态分配头结点的内存空间
    head->next = NULL;
    return head; // 返回头结点
}

void InsertStudent(LinkList head, int pos, int no, char *name) {
    Student *p = head;
    for (int i = 1; i < pos; i++) {
        if (p == NULL) return;
        p = p->next; // 找到需要插入的位置
    }
    Student *newStudent = (Student *)malloc(sizeof(Student)); // 动态分配一个新学生
    newStudent->no = no;
    strcpy(newStudent->name, name);
    newStudent->next = p->next; // 将新学生插入到链表中
    p->next = newStudent;
}

void PrintStudent(LinkList head) {
    Student *p = head->next;
    while (p != NULL) {
        printf("学号:%d 姓名:%s\n", p->no, p->name);
        p = p->next;
    }
    printf("\n");
}

int main() {
    LinkList head = InitList(); // 初始化链表
    InsertStudent(head, 1, 101, "小明"); // 插入学生
    InsertStudent(head, 2, 102, "小红");
    InsertStudent(head, 3, 103, "小刚");
    PrintStudent(head); // 输出链表
    return 0;
}

输出结果:

学号:101 姓名:小明
学号:102 姓名:小红
学号:103 姓名:小刚

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

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

相关文章

  • javascript定义变量时加var与不加var的区别

    JavaScript定义变量时加var与不加var的区别 在JavaScript中,定义变量时可以选择是否使用var关键字。这两种方式在作用域、变量提升和全局变量等方面有所不同。下面将详细讲解这两种方式的区别,并提供两个示例说明。 使用var关键字定义变量 当使用var关键字定义变量时,变量的作用域将限定在当前函数作用域或全局作用域中。这意味着在函数内部定义…

    other 2023年7月29日
    00
  • 2015第6周三ztree的使用

    2015第6周三ztree的使用攻略 zTree是一款基于jQuery的快速、简洁的多功能树形插件。本文将提供一个完整攻略,包括Tree基本使用方法、常配置选项、事件处理等内容,并提供两个示例如下。 1. zTree的基本使用方法 z的基本使用方法如下1. 引入jQuery和zTree的JavaScript文件。2. 在HTML页面中添加一个容器元素,用于显…

    other 2023年5月8日
    00
  • HTML仿命令行界面具体实现

    HTML仿命令行界面可以使用HTML、CSS和JavaScript实现,下面我将分步骤介绍具体实现方法。 1. HTML布局 首先,我们需要准备一个HTML文件,其中需要定义一个输入框和一个显示框,可以使用一个div元素来充当整个界面,如下所示: <div class="terminal"> <div class=&qu…

    other 2023年6月26日
    00
  • Java创建型设计模式之单例模式

    以下是使用Java创建型设计模式之单例模式的完整攻略: 单例模式概述 单例模式是一种创建型设计模式,用于确保一个类只有一个实例,并提供全局访问点。 实现单例模式的方法 Java中有多种实现单例模式的方法,下面介绍两种常用的方法。 方法一:饿汉式单例模式 饿汉式单例模式在类加载时就创建了实例,因此在多线程环境下也能保证只有一个实例。 示例代码如下: publi…

    other 2023年10月15日
    00
  • 通过注册表编辑器将复杂的命令操作集成到右键菜单

    当我们需要频繁输入复杂的命令行操作时,我们可以通过将其集成到右键菜单来方便我们的操作。这可以通过注册表编辑器实现。下面是具体的步骤: 步骤1:打开注册表编辑器 在Windows操作系统中,我们可以通过按下Win+R键打开运行窗口,输入“regedit”命令来打开注册表编辑器。 步骤2:创建新的菜单项 在注册表编辑器中,我们需要进入HKEY_CLASSES_R…

    other 2023年6月27日
    00
  • Java全面细致讲解类与对象

    Java全面细致讲解类与对象攻略 什么是类与对象 类是一种数据结构,用于表示一个抽象的概念。对象是类的一个实例,是一个具体的实体。例如,汽车是一个类,它可以表示汽车的共性,而一辆具体的汽车则是这个类的一个对象,它具有颜色、型号、品牌等具体的属性。 如何定义类 要定义一个类,需要使用关键字class,后面跟上类的名称以及一对大括号{},在大括号中可以定义类的属…

    other 2023年6月27日
    00
  • Java 继承方法实例详解

    Java 继承方法实例详解 继承是面向对象编程中一个重要的概念,它允许我们在已有类的基础上创建新的类,同时继承的子类也能够拥有基类的属性和方法。在 Java 中,继承是通过关键字 extends 实现的,本文将详细讲解 Java 继承方法的实现方式以及相关注意事项。 继承方法的实现方式 在 Java 中,子类可以继承父类中的所有公有方法和受保护方法(prot…

    other 2023年6月27日
    00
  • 浅谈标签和JLabel类构造方法 原创

    浅谈标签和JLabel类构造方法 介绍 在Java中,标签(Label)是一种用于显示文本或图像的组件。JLabel类是Swing库中的一个组件,用于创建和管理标签。本文将详细讲解JLabel类的构造方法以及如何使用它来创建和定制标签。 构造方法 JLabel类提供了多个构造方法,用于创建不同类型的标签。以下是常用的构造方法: 1. JLabel() 这是J…

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