C语言数据结构与算法之链表(一)

欢迎阅读本篇文章,本文将为大家详细讲解C语言中数据结构与算法之链表。接下来,将从以下几个方面为大家讲述:

  1. 链表的定义
  2. 链表的特点
  3. 链表的分类
  4. 单向链表的实现及应用
  5. 双向链表的实现及应用
  6. 示例说明

1. 链表的定义

链表是由一系列节点组合而成的数据结构,每个节点都包含了一个数据域和一个指向下一个节点的指针域。其中,链表的头结点为第一个节点,而尾节点为最后一个节点。链表通过指针连接各个节点,形成链式的数据存储结构。

2. 链表的特点

链表具有以下特点:

  1. 以节点为单位存储数据,节点之间通过指向下一个节点的指针相连。
  2. 链表的大小可动态变化,可以随时在链表中添加或删除节点。
  3. 链表可以高效地插入和删除元素,时间复杂度为O(1)。

3. 链表的分类

链表可以分为以下两种类型:

  1. 单向链表
    单向链表中的节点只含有一个指针域,指向下一个节点。

  2. 双向链表
    双向链表中的节点含有两个指针域,一个指向下一个节点,另一个指向前一个节点。

4. 单向链表的实现及应用

单向链表的实现比较简单,其中一个简单的实现方式是:

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

typedef struct node {
    int data;            // 数据域
    struct node *next;   // 指针域,指向下一个节点
} Node;

int main() {
    Node *head = (Node*) malloc(sizeof(Node));    // 头结点
    head -> next = NULL;                           // 初始化

    // 创建链表
    for(int i = 0; i < 5; i++) {
        Node *newNode = (Node*) malloc(sizeof(Node));
        newNode -> data = i;
        newNode -> next = head -> next;
        head -> next = newNode;
    }

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

    return 0;
}

单向链表的应用比较广泛,比如实现队列、链式栈和图等数据结构,甚至在一些算法题中也会用到。

5. 双向链表的实现及应用

双向链表相比单向链表,多出了一个指针来指向前面的节点。因此,双向链表有以下的实现方式:

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

typedef struct node {
    int data;            // 数据域
    struct node *prev;   // 指针域,指向前一个节点
    struct node *next;   // 指针域,指向下一个节点
} Node;

int main() {
    Node *head = (Node*) malloc(sizeof(Node));    // 头结点
    head -> prev = NULL;
    head -> next = NULL;

    // 创建链表
    Node *prev = head, *p = NULL;
    for(int i = 0; i < 5; i++) {
        p = (Node*) malloc(sizeof(Node));
        p -> data = i;
        p -> prev = prev;
        p -> next = NULL;
        prev -> next = p;
        prev = p;
    }

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

    return 0;
}

双向链表可以在单向链表的基础上,更方便地进行双向遍历以及双向查找。

6. 示例说明

下面,我们来看两个示例。

示例一:使用链表实现栈

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

typedef struct node {
    int data;            // 数据域
    struct node *next;   // 指针域,指向下一个节点
} Node;

typedef struct stack {
    Node *top;    // 栈顶指针
} Stack;

void InitStack(Stack *s) {
    s -> top = (Node*) malloc(sizeof(Node));    // 头结点
    s -> top -> next = NULL;
}

int IsEmpty(Stack *s) {
    return s -> top -> next == NULL;
}

void Push(Stack *s, int x) {
    Node *newNode = (Node*) malloc(sizeof(Node));
    newNode -> data = x;
    newNode -> next = s -> top -> next;
    s -> top -> next = newNode;
}

void Pop(Stack *s) {
    if(IsEmpty(s)) {
        printf("Error: Stack is empty!\n");
        return;
    }
    Node *temp = s -> top -> next;
    s -> top -> next = temp -> next;
    free(temp);
}

int Top(Stack *s) {
    if(IsEmpty(s)) {
        printf("Error: Stack is empty!\n");
        return -1;
    }
    return s -> top -> next -> data;
}

int main() {
    Stack s;
    InitStack(&s);
    Push(&s, 1);
    Push(&s, 2);
    Push(&s, 3);
    Pop(&s);
    Push(&s, 4);
    printf("%d\n", Top(&s));
    return 0;
}

以上代码使用单向链表实现了栈的基本操作,满足了栈的后进先出原则。

示例二:使用链表实现图

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

#define MAXVEX 100

typedef struct EdgeNode {
    int adjvex;                 // 邻接顶点在顶点数组中下标
    struct EdgeNode *next;      // 指向下一个邻接点
    int weight;                 // 边权值
} EdgeNode;

typedef struct VertexNode {
    int data;                   // 顶点信息
    EdgeNode *firstedge;        // 指向第一个邻接点
} VertexNode, AdjList[MAXVEX];

typedef struct GraphAdjList {
    AdjList adjList;            // 邻接表
    int numNodes, numEdges;     // 顶点数和边数
} GraphAdjList;

void CreateGraph(GraphAdjList *G) {
    int i, j, k, w;
    printf("Enter the number of nodes and edges: \n");
    scanf("%d%d", &G -> numNodes, &G -> numEdges);
    for(i = 0; i < G -> numNodes; i++) {
        printf("Enter vertex[%d] data: \n", i);
        scanf("%d", &G -> adjList[i].data);
        G -> adjList[i].firstedge = NULL;
    }
    for(k = 0; k < G -> numEdges; k++) {
        printf("Enter edge[%d] direction(i, j) and weight(w): \n", k);
        scanf("%d%d%d", &i, &j, &w);
        EdgeNode *e = (EdgeNode*) malloc(sizeof(EdgeNode));
        e -> adjvex = j;
        e -> weight = w;
        e -> next = G -> adjList[i].firstedge;
        G -> adjList[i].firstedge = e;
    }
}

void Print(GraphAdjList *G) {
    int i;
    EdgeNode *p;
    for(i = 0; i < G -> numNodes; i++) {
        printf("vertex[%d]: data=%d, edge=%d->", i, G -> adjList[i].data, i);
        p = G -> adjList[i].firstedge;
        while(p != NULL) {
            printf("%d(%d) ", p -> adjvex, p -> weight);
            p = p -> next;
        }
        printf("\n");
    }
}

int main() {
    GraphAdjList G;
    CreateGraph(&G);
    Print(&G);
    return 0;
}

以上代码使用单向链表实现了图的存储,并实现了基本的创建和输出操作。其中,每个顶点通过一个边链表来存储与之相邻接的顶点。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构与算法之链表(一) - Python技术站

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

相关文章

  • Java常见数据结构面试题(带答案)

    Java常见数据结构面试题(带答案)完整攻略 介绍 在Java面试中,数据结构不可避免地成为一部分的考察内容。因此,掌握Java常见数据结构,对于提高面试成功率十分必要。本篇攻略将会介绍常见的Java数据结构,并提供相应的面试题目和答案,希望可以帮助面试者在面试当中更好地展示自己的实力。 目录 结构体 数组 链表 栈 队列 树 哈希表 结构体 在Java中并…

    数据结构 2023年5月17日
    00
  • 线段树好题! P2824 [HEOI2016/TJOI2016]排序 题解

    题目传送门 前言 线段树好题!!!!咕咕了挺久的一道题目,很早之前就想写了,今天终于找了个时间A掉了。 题意 给定一个 \(1\) 到 \(n\) 的排列,有 \(m\) 次操作,分两种类型。1.0 l r表示将下标在 \([l, r]\) 区间中的数升序排序。2.1 l r表示将下标在 \([l, r]\) 区间中的数降序排序。给定一个数 \(q\) 询问…

    算法与数据结构 2023年4月17日
    00
  • C语言数据结构系列之树的概念结构和常见表示方法

    C语言数据结构系列之树的概念结构和常见表示方法 树是一种非线性数据结构,它由若干个节点构成,节点之间通过边来连接,具有层次关系。 树的基本概念和术语 节点:树中的元素,它可以包含一个数据元素或多个数据元素,一个节点也可以称为一个分支节点。 根节点:树的最上层节点,它没有父节点。 叶子节点:没有子节点的节点称为叶子节点。 父节点和子节点:父节点是某个节点的上一…

    数据结构 2023年5月17日
    00
  • 「学习笔记」AC 自动机

    「学习笔记」AC 自动机 点击查看目录 目录 「学习笔记」AC 自动机 算法 问题 思路 代码 例题 Keywords Search 玄武密码 单词 病毒 最短母串 文本生成器 背单词 密码 禁忌 前置:「学习笔记」字符串基础:Hash,KMP与Trie。 好像对例题的讲解越来越抽象了? 算法 问题 求 \(n\) 个单词在一个长度为 \(m\) 的文章里出…

    算法与数据结构 2023年5月5日
    00
  • R语言数据结构之矩阵、数组与数据框详解

    R语言数据结构之矩阵、数组与数据框详解 在R语言中,矩阵、数组和数据框是常见的数据结构。本文将从定义、创建、访问和操作等方面详细讲解这些数据结构。 矩阵(matrix) 定义 矩阵是R语言中的一种二维数据结构,所有的元素都必须是同一类型的,并且矩阵中的行列数必须相同。矩阵可以使用matrix函数创建。 创建 # 创建一个3行4列的矩阵,所有元素都为0 mat…

    数据结构 2023年5月17日
    00
  • 算法总结–ST表

    声明(叠甲):鄙人水平有限,本文为作者的学习总结,仅供参考。 1. RMQ 介绍 在开始介绍 ST 表前,我们先了解以下它以用的场景 RMQ问题 。RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ…

    算法与数据结构 2023年4月18日
    00
  • 一些常见的字符串匹配算法

    作者:京东零售 李文涛 一、简介 1.1 Background 字符串匹配在文本处理的广泛领域中是一个非常重要的主题。字符串匹配包括在文本中找到一个,或者更一般地说,所有字符串(通常来讲称其为模式)的出现。该模式表示为p=p[0..m-1];它的长度等于m。文本表示为t=t[0..n-1],它的长度等于n。两个字符串都建立在一个有限的字符集上。 一个比较常见…

    算法与数据结构 2023年4月25日
    00
  • Java数据结构之图的路径查找算法详解

    Java数据结构之图的路径查找算法详解 什么是图? 在计算机科学中,图是一种非常常见的数据结构,用于表示图形和网络等概念。图由节点和边组成,其中节点表示实体,边表示这些实体之间的关系。节点和边可以表示各种各样的实体和关系,因此图在计算机科学中具有广泛的应用。 图的路径查找算法 路径查找算法是一个用途广泛的算法,它用于查找从一个节点到另一个节点的路径。在图中,…

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