C语言实现无头单链表详解

yizhihongxing

C语言实现无头单链表详解

什么是无头单链表?

单链表是一种非常常见的数据结构,它由一个个结点组成,每个结点包含两部分:数据部分和next指针部分。数据部分可以存放任何类型的数据,next指针则用于连接下一个结点。

而无头单链表与单链表类似,只是它没有头结点。头结点一般来说用于存放链表的长度、头指针等信息,而无头单链表只有一个指向第一个结点的指针,也就是没有这些额外的信息。

如何实现无头单链表?

下面我们来介绍如何用C语言实现无头单链表。

首先,定义一个结构体来表示单链表的结点:

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

其中,data表示结点中存放的数据,next表示指向下一个结点的指针。

接下来,定义一个指向第一个结点的指针:

Node *head = NULL;

表示空链表。

插入结点

下面是向链表中插入一个新结点的代码:

Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = head;
head = newNode;

其中,先创建一个新结点newNode,并将其data域赋值为新插入的数据,next域赋值为head。然后将新的头结点指针head指向newNode。

这段代码的作用是将新结点插入到链表的最前面。

删除结点

下面是删除链表中第一个出现的某个元素的代码:

Node *current = head;
Node *previous = NULL;
while (current != NULL && current->data != data) {
    previous = current;
    current = current->next;
}
if (current != NULL) {
    if (previous == NULL) {
        head = current->next;
    } else {
        previous->next = current->next;
    }
    free(current);
}

其中,current表示要删除的结点,previous表示current前面的结点。遍历链表找到要删除的结点后,如果previous为空,表示要删除的是头结点,需要将head指向当前结点的next域。否则,将previous的next指针指向current的next指针,即为删除操作。

示例说明

我们来看一个简单的示例,创建一个空的链表,插入三个结点,然后删除第二个结点:

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

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

int main() {
    Node *head = NULL;
    int data[] = {1, 2, 3};
    int i;

    // 插入结点
    for (i = 0; i < 3; i++) {
        Node *newNode = (Node*)malloc(sizeof(Node));
        newNode->data = data[i];
        newNode->next = head;
        head = newNode;
    }

    // 遍历链表
    Node *current = head;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");

    // 删除结点
    Node *previous = NULL;
    current = head;
    while (current != NULL && current->data != 2) {
        previous = current;
        current = current->next;
    }
    if (current != NULL) {
        if (previous == NULL) {
            head = current->next;
        } else {
            previous->next = current->next;
        }
        free(current);
    }

    // 遍历链表
    current = head;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");

    return 0;
}

输出结果为:

3 2 1 
3 1 

这个示例展示了如何创建一个无头单链表,向链表中插入元素,并删除其中的一项,最后输出结果。

再看一个示例,把链表逆序输出:

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

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

Node *reverse(Node *head) {
    Node *newHead = NULL;
    while (head != NULL) {
        Node *next = head->next;
        head->next = newHead;
        newHead = head;
        head = next;
    }
    return newHead;
}

int main() {
    Node *head = NULL;
    int data[] = {1, 2, 3, 4, 5};
    int i;

    // 插入结点
    for (i = 0; i < 5; i++) {
        Node *newNode = (Node*)malloc(sizeof(Node));
        newNode->data = data[i];
        newNode->next = head;
        head = newNode;
    }

    // 反转链表
    Node *newHead = reverse(head);

    // 遍历链表
    Node *current = newHead;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");

    return 0;
}

这个示例演示了如何把无头单链表逆序输出,在reverse函数中,不断将head指向的结点插入到newHead之前,从而实现链表逆序。

输出结果为:

5 4 3 2 1 

总结

本文介绍了如何用C语言实现无头单链表,包括插入结点、删除结点、遍历链表、逆序输出链表等操作。使用无头单链表时需要注意,它没有头结点,需要特别处理链表是否为空的情况。同时,无头单链表是一种简单而有效的数据结构,用于存储大小不确定的数据,应用广泛。

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

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

相关文章

  • 深度解析C语言中数据的存储

    深度解析C语言中数据的存储 什么是数据的存储? 在程序中,我们通常需要定义一些数据类型来存储各种不同类型的数据。而这些数据的存储是指这些数据在内存中的分配和管理。在C语言中,内存被分成了两个部分,分别是栈和堆。 栈和堆 栈 栈是运行程序时直接存储基本数据类型和函数调用时使用的一块内存区域。一般情况下,栈空间是由系统进行分配和释放的,并且栈空间的大小是固定的。…

    other 2023年6月27日
    00
  • C 语言基础教程(我的C之旅开始了)[六]

    下面是C语言基础教程(我的C之旅开始了)[六]的完整攻略。 标题 C语言基础教程(我的C之旅开始了)[六] 内容 本篇教程主要讲解指针和数组的关系,具体内容如下: 指针 定义指针变量 指针是一种特殊的变量,它存储了一个地址值,可以用来访问该地址所对应的数据。定义指针变量的方法如下: int *p; char *q; 其中,int p表示定义一个指向整型数据的…

    other 2023年6月27日
    00
  • Android实现可滑动的自定义日历控件

    Android实现可滑动的自定义日历控件攻略 1. 概述 在Android中实现可滑动的自定义日历控件可以提供用户友好的日历浏览体验。本攻略将介绍一种实现方法,使用RecyclerView和自定义Adapter来展示日历,并通过手势监听实现滑动功能。 2. 步骤 2.1 创建项目和布局文件 首先,创建一个新的Android项目,并在布局文件中添加一个Recy…

    other 2023年9月6日
    00
  • 无线路由器的ip地址忘了的解决办法

    无线路由器的IP地址忘了的解决办法攻略 如果你忘记了无线路由器的IP地址,不用担心,以下是一份详细的解决办法攻略,帮助你找回路由器的IP地址。 步骤1:查找路由器的默认IP地址 大多数无线路由器都有一个默认的IP地址,你可以通过以下几种方式来查找它: 查找路由器的用户手册:在路由器的用户手册中,你可以找到关于默认IP地址的信息。手册通常会提供一个默认的管理网…

    other 2023年7月30日
    00
  • Java的三种代理模式简述

    Java的三种代理模式简述 Java的三种代理模式为静态代理、动态代理和CGLIB代理。 一、静态代理 静态代理指的是代理对象在编译期已经确定的情况下所使用的代理模式。代理类与委托类实现了相同的接口,代理类对目标对象进行了包装,所以在调用目标对象时需要通过代理对象来执行。静态代理在性能方面较差,但是实现较为简单,常用于简单业务场景。 示例: interfac…

    other 2023年6月26日
    00
  • C/C++合并两个升序链表的方式

    当合并两个已按升序排列的链表时,可以使用指针遍历两个链表,并选择合适的节点插入到一个新链表中。以下是一般的步骤: 创建一个新链表的头结点,并用指针指向它。 使用两个指针,一个指向第一个链表的头结点,另一个指向第二个链表的头结点。 遍历两个链表直到其中一个链表已到达结尾。在每次遍历时选择相对较小的节点并插入到新链表。 如果其中一个链表到达结尾而另一个链表仍然有…

    other 2023年6月27日
    00
  • js嵌套的数组扁平化:将多维数组变成一维数组以及push()与concat()区别的讲解

    一、什么是js嵌套的数组扁平化 当一个数组中嵌套了多个数组时,我们把这种数组称为多维数组。而将多维数组变成一维数组的操作就被称为数组扁平化。js嵌套的数组扁平化就是将多维数组变成一维数组的过程,使得多维数组中的元素都能展开成一维数组。 二、js嵌套数组扁平化的实现方式 实现js嵌套数组扁平化有多种方式,例如用递归、利用数组的flat()方法等,这里介绍一种比…

    other 2023年6月25日
    00
  • postgresql中使用distinct去重

    PostgreSQL中使用DISTINCT去重 在数据处理中,经常会遇到需要把重复的数据去重的情况。PostgreSQL中,我们可以使用DISTINCT关键字来实现去重。本文将介绍如何在PostgreSQL中使用DISTINCT关键字去除数据中的重复项。 使用方法 在一个SELECT查询中,我们可以使用DISTINCT关键字来过滤掉重复数据。具体代码如下所示…

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