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日

相关文章

  • 回溯理论基础及leetcode例题

    学习参考 回溯 与递归相辅相成;回溯是递归的副产品,只要有递归就会有回溯。回溯函数也就是递归函数,指的都是一个函数。 回溯搜索法 纯暴力搜索解决的问题 组合问题:N个数里面按一定规则找出k个数的集合切割问题:一个字符串按一定规则有几种切割方式子集问题:一个N个数的集合里有多少符合条件的子集排列问题:N个数按一定规则全排列,有几种排列方式(与组合差别,排列有元…

    算法与数据结构 2023年4月17日
    00
  • C语言全面讲解顺序表使用操作

    C语言全面讲解顺序表使用操作 什么是顺序表 顺序表(Sequential List)是一种常见的数据结构,它由一组连续的存储单元组成,并且支持随机访问。通常我们使用数组来实现顺序表。 顺序表的基本操作 初始化 在使用顺序表之前,需要先进行初始化。顺序表的初始化包括两个步骤:指定顺序表的大小,申请内存空间。具体代码如下: #define MAXSIZE 100…

    数据结构 2023年5月17日
    00
  • Java数据结构之图的基础概念和数据模型详解

    Java数据结构之图的基础概念和数据模型详解 简介 图是一种非常重要的数据结构,在计算机科学和实际应用中广泛使用。比如搜索引擎中的网页之间的链接关系就可以用图来表示和处理。在本文中,我们将详细讲解图的基础概念和数据模型。同时,我们将通过两个实例来进一步说明图的应用。 图的基础概念 什么是图 图是由若干个节点(顶点)和连接节点的边组成的一种数据结构。一个图可以…

    数据结构 2023年5月17日
    00
  • 常用内核架构

      本文分享自天翼云开发者社区《常用内核架构》,作者:JackW   宏内核 应用程序调用内存分配的 API(应用程序接口)函数。 处理器切换到特权模式,开始运行内核代码。 内核里的内存管理代码按照特定的算法,分配一块内存。 把分配的内存块的首地址,返回给内存分配的 API 函数。 内存分配的 API 函数返回,处理器开始运行用户模式下的应用程序,应用程序就…

    算法与数据结构 2023年4月22日
    00
  • C++数据结构之红黑树的实现

    《C++数据结构之红黑树的实现》是一篇介绍红黑树实现的文章,通过本文,你可以了解到什么是红黑树以及如何实现红黑树。 什么是红黑树 红黑树是一种自平衡的二叉查找树,它具有良好的平衡性和查找性能。红黑树可以在O(log n)的时间内完成查找、插入和删除操作。 红黑树的一个重要性质是它的任何一个节点都有一个颜色(红色或黑色)属性。在插入、删除操作中,需要通过一定的…

    数据结构 2023年5月17日
    00
  • 【牛客小白月赛70】A-F题解【小d和超级泡泡堂】【小d和孤独的区间】【小d的博弈】【小d和送外卖】

    比赛传送门:https://ac.nowcoder.com/acm/contest/53366 难度适中。 ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?? 阅读原文获得更好阅读体验:https://www.erikt…

    算法与数据结构 2023年4月17日
    00
  • MySQL优化及索引解析

    MySQL是业界常用的关系型数据库管理系统之一,作为程序员,我们需要了解如何对MySQL进行优化,以提高数据库的性能。下面是MySQL优化及索引解析的完整攻略。 目录 优化查询语句 优化数据库设计 优化服务器架构 索引优化 实例分析 优化查询语句 查询语句是应用程序与数据库之间的桥梁,优化查询语句可以大大提高数据库的性能。以下是一些优化查询语句的方法: 使用…

    数据结构 2023年5月17日
    00
  • JavaScript 数据结构之散列表的创建(2)

    下面是详细讲解“JavaScript 数据结构之散列表的创建(2)”的完整攻略。 散列表(哈希表) 散列表是一种数据结构,使用哈希函数将键映射到索引。散列表可以在常量时间 O(1) 中进行插入、删除和查找操作,但也具有碰撞冲突问题。 碰撞冲突问题 在散列表中,当两个不同的键通过哈希函数映射到了同一个索引位置时,就会发生碰撞冲突问题。解决碰撞冲突问题的方法有很…

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