C语言学习之链表的实现详解

下面我将详细讲解“C语言学习之链表的实现详解”的完整攻略。

1. 链表的定义

链表是一种数据结构,它由一系列节点组成。每个节点由一个数据部分和一个指向下一个节点的地址部分组成。链表可以有多种形式,例如单向链表、双向链表、循环链表等。

2. 链表的实现

2.1. 单向链表

单向链表是最简单的链表形式,一个节点只包含一个指向下一个节点的指针。在C语言中,我们可以使用结构体来表示一个节点,如下所示:

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

链表的头指针指向第一个节点的地址,如果为空链表则指向 NULL。可以定义如下:

struct Node* head = NULL;

可以通过遍历链表找到某个节点,如下所示:

struct Node* p = head;
while(p != NULL && p->data != target){
    p = p->next;
}

其它操作,例如插入节点、删除节点等,也比较容易实现。

2.2. 双向链表

双向链表是一种带有前向指针和后向指针的链表结构。每个节点都有一个指向前驱节点的指针和一个指向后继节点的指针。定义如下:

struct DNode{
    int data;
    struct DNode* prev;
    struct DNode* next;
};

可以通过前向、后向指针轻松在双向链表上进行遍历和操作。

2.3. 循环链表

循环链表是一种特殊的链表,最后一个节点的后继指针指向第一个节点。定义与单向链表和双向链表类似,只是需要注意循环链接的实现。

3. 示例说明

下面我们看两个示例,分别是单向链表和双向链表的实现。

3.1. 单向链表示例

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

/*定义节点类型*/
struct Node{
    int data;
    struct Node* next;
};

/*头插法插入节点*/
void insertAtHead(struct Node** headRef, int data){
    /*创建节点*/
    struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
    new_node->data = data;
    /*将新节点插入链表头部*/
    new_node->next = (*headRef);
    (*headRef) = new_node;
}

/*尾插法插入节点*/
void insertAtTail(struct Node** headRef, int data){
    /*创建节点*/
    struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
    new_node->data = data;
    new_node->next = NULL;

    if((*headRef) == NULL){
        (*headRef) = new_node;
        return;
    }

    struct Node* p = (*headRef);
    while(p->next != NULL){
        p = p->next;
    }
    p->next = new_node;
}

/*删除节点*/
void deleteNode(struct Node** headRef, int target){
    /*如果要删除的节点是头节点*/
    if((*headRef) != NULL && (*headRef)->data == target){
        (*headRef) = (*headRef)->next;
        return;
    }

    struct Node* p = (*headRef);
    struct Node* prev = NULL;
    while(p != NULL && p->data != target){
        prev = p;
        p = p->next;
    }
    /*如果找到目标节点*/
    if(p != NULL){
        prev->next = p->next;
        free(p);
    }
}

/*打印链表*/
void printList(struct Node* head){
    struct Node* p = head;
    while(p != NULL){
        printf("%d ", p->data);
        p = p->next;
    }
}

int main(){
    struct Node* head = NULL;

    insertAtHead(&head, 2);
    insertAtHead(&head, 1);
    insertAtTail(&head, 3);
    insertAtTail(&head, 4);

    printList(head);

    deleteNode(&head, 3);
    deleteNode(&head, 1);

    printList(head);

    return 0;
}

3.2. 双向链表示例

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

/*定义节点类型*/
struct DNode{
    int data;
    struct DNode* prev;
    struct DNode* next;
};

/*头插法插入节点*/
void insertAtHead(struct DNode** headRef, int data){
    /*创建节点*/
    struct DNode* new_node = (struct DNode*)malloc(sizeof(struct DNode));
    new_node->data = data;

    /*插入链表头*/
    new_node->prev = NULL;
    new_node->next = (*headRef);
    if((*headRef) != NULL){
        (*headRef)->prev = new_node;
    }
    (*headRef) = new_node;
}

/*尾插法插入节点*/
void insertAtTail(struct DNode** headRef, int data){
    /*创建节点*/
    struct DNode* new_node = (struct DNode*)malloc(sizeof(struct DNode));
    new_node->data = data;
    new_node->next = NULL;

    if((*headRef) == NULL){
        new_node->prev = NULL;
        (*headRef) = new_node;
        return;
    }

    struct DNode* p = (*headRef);
    while(p->next != NULL){
        p = p->next;
    }
    new_node->prev = p;
    p->next = new_node;
}

/*删除节点*/
void deleteNode(struct DNode** headRef, int target){
    struct DNode* p = (*headRef);
    while(p != NULL && p->data != target){
        p = p->next;
    }
    /*如果要删除的节点是头节点*/
    if(p != NULL && p == (*headRef)){
        (*headRef) = p->next;
        if((*headRef) != NULL){
            (*headRef)->prev = NULL;
        }
        free(p);
        return;
    }
    /*如果找到目标节点*/
    if(p != NULL){
        p->prev->next = p->next;
        if(p->next != NULL){
            p->next->prev = p->prev;
        }
        free(p);
    }
}

/*打印链表(正序)*/
void printList(struct DNode* head){
    struct DNode* p = head;
    while(p != NULL){
        printf("%d ", p->data);
        p = p->next;
    }
}

/*打印链表(反序)*/
void printListReverse(struct DNode* head){
    struct DNode* p = head;
    while(p != NULL && p->next != NULL){
        p = p->next;
    }
    while(p != NULL){
        printf("%d ", p->data);
        p = p->prev;
    }
}

int main(){
    struct DNode* head = NULL;

    insertAtHead(&head, 2);
    insertAtHead(&head, 1);
    insertAtTail(&head, 3);
    insertAtTail(&head, 4);

    printList(head);
    printf("\n");
    printListReverse(head);

    deleteNode(&head, 3);
    deleteNode(&head, 1);

    printf("\n");
    printList(head);

    return 0;
}

以上就是链表的实现攻略和两个示例的说明,希望对你有所帮助。

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

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • c++ 数据结构map的使用详解

    c++ 数据结构map的使用详解 什么是map map是C++ STL中提供的一种用以存储键值对(key-value)的容器。它能够以平均O(log n)复杂度进行搜索、插入、删除操作,并且保持元素顺序,是一种比较高效的数据结构。 map的基本用法 定义map 定义map需要包含头文件<map>。 语法:map<key_type, valu…

    数据结构 2023年5月17日
    00
  • Go语言数据结构之插入排序示例详解

    Go语言数据结构之插入排序示例详解 什么是插入排序? 插入排序是一种简单直观的排序方法,其基本思想是将一个待排序的序列分成已排序和未排序两部分,从未排序的部分中选择一个元素插入到已排序部分的合适位置,直到所有元素都被插入到已排序部分为止。 插入排序示例 示例1 我们来看一个数字序列的插入排序示例: package main import "fmt&…

    数据结构 2023年5月17日
    00
  • 详解python数据结构之队列Queue

    详解Python数据结构之队列 (Queue) 在计算机科学中,队列(Queue)是一种数据结构,可以用于按顺序存储和访问元素。该数据结构遵循先进先出(FIFO)原则,人们可以从队列的前面插入元素,从队列的后面删除元素。Python内置了队列模块(queue),这个模块实现了多线程安全队列、同步机制及相关数据结构。Queue模块提供了三种队列类型: FIFO…

    数据结构 2023年5月17日
    00
  • 排序算法之详解选择排序

    引入 选择排序顾名思义是需要进行选择的,那么就要问题了,选择到底是选择什么呢? 选择排序的选择是选择数组中未排序的数组中最小的值,将被选择的元素放在未排序数组的首位 如果你对 ‘未排序数组’ , ‘选择’ 的概念不理解,那么你可以看看下面的图 思路 有了上面的一些基础之后,我们再来说说选择排序算法的思路 不断的选择未排序数组中最小的值,将其与未排序数组的首位…

    算法与数据结构 2023年4月25日
    00
  • qqwry.dat的数据结构图文解释第2/2页

    首先,对于“qqwry.dat的数据结构图文解释第2/2页”这个主题,我们需要先对其进行一些介绍。 qqwry.dat是一种IP地址转换工具,它可以将一个给定的IP地址转换成一个物理地址。它的数据结构是一种二叉查找树,在此二叉查找树中每个节点保存了一个IP地址段和该段IP地址所对应的物理地址的信息。这个数据结构的结构图可以在“qqwry.dat的数据结构图文…

    数据结构 2023年5月17日
    00
  • Java数据结构之链表实现(单向、双向链表及链表反转)

    Java数据结构之链表实现 链表基础概念 链表是一种数据结构,它由一系列节点(Node)组成,每个节点包含两个部分,一个是数据域(data),一个是指针域(next)。数据域存储数据信息,指针域指向下一个节点。 链表的种类很多,比如单向链表、双向链表、循环链表等等。 单向链表:链表的每个节点只有一个指针域,指向下一个节点。 双向链表:链表的每个节点有两个指针…

    数据结构 2023年5月17日
    00
  • Codeforces Round 866 (Div. 2)

    A. Yura’s New Name 题意: 给出一个仅由_或^组成的字符串,你可以在任意位置添加_或^字符,使得字符串满足:任意字符要么属于^_^的一部分,要么属于^^的一部分。求最少添加的字符数量。 分析: 对于_我们只需处理没有组成^_^的_: ①如果_在首位置且左边没有^则添加^ ②如果_在尾位置且右边没有^则添加^ ③如果_在中间部分且右边没有^则…

    算法与数据结构 2023年4月25日
    00
  • 数据结构中的各种排序方法小结(JS实现)

    数据结构中的各种排序方法小结(JS实现) 本文将介绍常见的八种排序算法: 冒泡排序 插入排序 选择排序 快速排序 归并排序 堆排序 希尔排序 计数排序 下面进行详细讲解。 冒泡排序 冒泡排序是一种简单的排序算法,它重复地遍历数组,比较相邻的两个元素,并按大小交换位置,一直到整个数组排序完成。它的时间复杂度为O(n^2)。 示例代码: function bub…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部