C语言 超详细模拟实现单链表的基本操作建议收藏

C语言 超详细模拟实现单链表的基本操作建议收藏

前言

单链表是C语言数据结构中十分基础的一种。以下是单链表的定义:

typedef struct Node {
    int val;
    struct Node *next;
} Node, *LinkedList;

其中,Node 表示单链表中的一个节点,包括 val 和指向下一个节点的指针 next。而 LinkedList 则是指向单链表第一个节点的指针。

基本操作

1. 初始化单链表

初始化单链表,可以简单地将 LinkedList 指针赋值为 NULL

LinkedList initList() {
    LinkedList head = NULL;
    return head;
}

2. 判断单链表是否为空

首先判断单链表的头节点是否为空,即指向的节点是否为 NULL

int isEmpty(LinkedList head) {
    if(head == NULL) {
        return 1;
    } else {
        return 0;
    }
}

3. 获取单链表长度

从头节点开始遍历单链表,每遍历一个节点计数器加1,直到遍历到链表尾节点为止:

int length(LinkedList head) {
    int len = 0;
    Node *p = head;
    while(p != NULL) {
        len++;
        p = p->next;
    }
    return len;
}

4. 遍历单链表

从头节点开始遍历单链表,输出所有节点的 val 值:

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

5. 在单链表末尾插入节点

从头节点开始遍历单链表,找到链表尾节点,将其指针指向新节点:

LinkedList insertAtTail(LinkedList head, int val) {
    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->val = val;
    newNode->next = NULL;
    if(head == NULL) {
        head = newNode;
    } else {
        Node *p = head;
        while(p->next != NULL) {
            p = p->next;
        }
        p->next = newNode;
    }
    return head;
}

6. 在单链表指定位置插入节点

从头节点开始遍历单链表,找到指定位置的前驱节点,将其指针指向新节点,将新节点指针指向后继节点:

LinkedList insertAtIndex(LinkedList head, int index, int val) {
    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->val = val;
    newNode->next = NULL;
    if(head == NULL && index != 1) {
        printf("Error: Invalid Index\n");
        return NULL;
    } else if(index == 1) {
        newNode->next = head;
        head = newNode;
    } else {
        int i = 1;
        Node *p = head;
        while(i < index - 1 && p != NULL) {
            p = p->next;
            i++;
        }
        if(p == NULL) {
            printf("Error: Invalid Index\n");
            return NULL;
        }
        newNode->next = p->next;
        p->next = newNode;
    }
    return head;
}

7. 在单链表中删除节点

从头节点开始遍历单链表,找到指定节点的前驱节点,将其指针指向后继节点,将该节点从内存中删除:

LinkedList deleteNode(LinkedList head, int val) {
    if(head == NULL) {
        printf("Error: List is Empty\n");
        return NULL;
    }
    Node *p = head;
    Node *pre = NULL;
    while(p != NULL && p->val != val) {
        pre = p;
        p = p->next;
    }
    if(p == NULL) {
        printf("Error: No Element Found\n");
    } else if(pre == NULL) {
        head = p->next;
        free(p);
    } else {
        pre->next = p->next;
        free(p);
    }
    return head;
}

示例说明

示例1

int main() {
    LinkedList head = initList();
    head = insertAtTail(head, 1);
    head = insertAtTail(head, 2);
    head = insertAtTail(head, 3);
    head = insertAtTail(head, 4);
    head = insertAtIndex(head, 2, 5);
    head = deleteNode(head, 3);
    traverseList(head);
    return 0;
}

输出:

1 5 2 4

示例2

int main() {
    LinkedList head = initList();
    printf("%d\n", isEmpty(head));
    head = insertAtTail(head, 1);
    head = insertAtTail(head, 2);
    printf("%d\n", length(head));
    traverseList(head);
    head = deleteNode(head, 3);
    head = deleteNode(head, 2);
    head = deleteNode(head, 1);
    printf("%d\n", isEmpty(head));
    traverseList(head);
    return 0;
}

输出:

1
2
1 2
Error: No Element Found
Error: No Element Found
1

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言 超详细模拟实现单链表的基本操作建议收藏 - Python技术站

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

相关文章

  • AngularJS $on、$emit和$broadcast的使用

    AngularJS $on、$emit和$broadcast的使用攻略 AngularJS提供了三个重要的事件传播机制:$on、$emit和$broadcast。这些机制允许在应用程序的不同部分之间进行事件通信。下面是它们的详细说明和使用示例。 $on $on方法用于在当前作用域中监听一个事件。当事件被触发时,注册的回调函数将被执行。以下是$on的语法: $…

    other 2023年8月20日
    00
  • vite+vue3中使用mock模拟数据问题

    vite+vue3的开发中,我们希望在开发过程中使用mock数据进行测试,而不是依赖于后端API接口。这样可以在不影响后端开发的情况下,快速开发并测试前端页面。在这里,我们提供一个完整的攻略,介绍如何在vite+vue3中使用mock模拟数据。 1. 安装mockjs 首先,在项目根目录下,使用npm或者yarn安装mockjs: npm install m…

    other 2023年6月27日
    00
  • 获取控件大小和设置调整控件的位置XY示例

    获取控件大小和设置调整控件位置XY是页面布局中非常重要的操作。下面提供两个示例,分别介绍如何获取控件大小以及如何调整控件的位置。 示例1:获取控件大小 获取控件大小的方法可以通过JavaScript中的offsetWidth和offsetHeight属性来实现。下面是一个示例代码,可以获取DIV控件的宽度和高度: <div id="myDiv…

    other 2023年6月27日
    00
  • 微信小程序页面间值传递的两种方法

    微信小程序页面间值传递的两种方法 微信小程序是一种轻量级的应用程序,它允许开发者创建具有独立功能的页面。在小程序中,有时需要在不同的页面之间传递数据。下面将介绍两种常用的方法来实现微信小程序页面间值传递。 方法一:通过URL参数传递值 这种方法适用于需要在页面跳转时传递少量数据的情况。具体步骤如下: 在源页面中,使用wx.navigateTo或wx.redi…

    other 2023年7月29日
    00
  • JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)

    下面我将详细讲解JavaScript继承的基础知识,包括原型链继承、借用构造函数继承、混合模式继承、原型式继承、寄生式继承和寄生组合式继承。 原型链继承 JavaScript使用原型链的方式实现继承,通过将一个对象的原型指向另一个对象来实现继承。 示例代码如下: // 创建一个父对象,包含属性和方法 var parent = { name: ‘Bob’, a…

    other 2023年6月26日
    00
  • 下载文件个别浏览器文件名乱码解决办法

    下面是“下载文件个别浏览器文件名乱码解决办法”的完整攻略: 问题描述 有时在下载文件时,某些浏览器(尤其是一些非主流浏览器和非英文浏览器)会出现文件名乱码的情况,导致下载下来的文件无法正确显示其名称。这种情况下,我们需要解决文件名乱码的问题。 解决办法 方法1. 使用HTTP头信息中的charset参数指定字符集。 在HTTP头信息中,可以使用charset…

    other 2023年6月26日
    00
  • .NET 线程基础的使用介绍

    .NET 线程基础的使用介绍 线程基本概念 在计算机中,线程(Thread)是指程序执行流的最小单元,它是进程(Process)的一个子集,是操作系统分配处理器时间的基本单位。在 .NET 中,线程是由 System.Threading.Thread 类代表的。 创建线程 在 .NET 中,创建一个新线程的基本方法是实例化 Thread 类并指定一个方法来启…

    other 2023年6月27日
    00
  • 小程序自定义组件全局样式不生效的解决方法

    当我们在小程序中使用自定义组件时,有时我们希望在组件中设置全局样式,但是发现这些样式并没有生效。这种情况通常是因为小程序默认会对组件的样式进行隔离,所以全局样式无法生效。解决方法如下: 1. 使用 wxss 文件实现全局样式 在小程序的根目录新建一个 app.wxss 文件,并在此文件中定义全局样式。然后在自定义组件中通过 @import 引入 app.wx…

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