数据结构与算法分析—— 1、链表

  链表是一种最简单的数据结构,当我们在使用数组存储数据的时候,频繁的插入和删除会损耗大量的性能,而链表正是一种适合频繁插入删除操作的线性数据结构。

  有关链表的详细介绍可以看这里,通俗的来说,链表就是由一些节点构成,每个节点有一个指针,这个指针保存着下一个节点的位置。因此,链表就是由指针将这些物理上没有逻辑关系的节点连接了起来,构成一个有关系的线性表。

  我们先来看“单链表”,在C语言当中,具有封装能力的数据类型是结构体。因此,我们用一个结构体来表示一个节点。定义如下:

1 struct Node{
2      ElementType Element;
3      struct Node * Next;
4 };

  在这里,我们假设元素的类型为 int ,于是这样定义:

1 typedef int ElementType;

  对于一个链表,它的基本操作有:判断链表是否为空、当前元素是否为最后一个、查找一个元素、插入一个元素、删除一个元素、删除整个表等。所以我们有如下声明:

1 int IsEmpty(List L);
2 int IsLast(Position P);
3 Position Find(ElementType X, List L);
4 void Delete(ElementType X, List L);
5 void Insert(ElementType X, Position P);
6 void DeleteList(List L);

  对了,忘了类型定义了。使用类型定义可以让代码看起来更简洁,也更容易理解。Position 和 List 类型都是“指向Node的指针”,不过我们用 List 来表示头结点,Position 来表示任意节点。这样,程序一目了然。

1 typedef struct Node * PtrToNode;
2 typedef PtrToNode List;
3 typedef PtrToNode Position;

  接下来就是实现了,我们先从判断链表是否为空开始。我们传入头指针,只需要判断头结点的 Next 指针是否为 NULL 即可。若 Next 为 NULL,说明链表只有头结点,为空。

1 int
2 IsEmpty(List L) {
3     return L->Next == NULL;
4 }

  判断当前元素是否为最后一个元素的方式也与此类似,因为当一个结点处于末尾时,它的 Next 指针为 NULL。

1 int
2 IsLast(Position P) {
3     return P->Next == NULL;
4 }

  然后我把接下来的几个函数的实现全部放出来,都是很容易理解的。

 1 Position
 2 Find(ElementType X, List L) {
 3     Position P;
 4     P = L->Next;
 5     while (P != NULL && P->Element != X) {
 6         P = P-Next;
 7     }
 8     return P;
 9 }
10
11 void
12 Insert(ElementType X, Position P) {
13     Position temp;
14     temp = malloc(sizeof(struct Node));
15
16     temp->Element = X;
17     temp->Next = P->Next;
18     P->Next = temp;
19 }
20
21 void
22 DeleteList(List L) {
23     Position P, temp;
24     P = L->Next;
25     L-Next = NULL;
26     while (P != NULL) {
27         temp = P->Next;
28         free(P);
29         P = temp;
30     }
31 }
32
33 void
34 Delete(ElementType X, List L) {
35     Position P, temp;
36     P = FindPrevious(X,L); //找到X的前一个元素
37     if (!IsLast(P,L)) {
38          temp = P->Next;
39          P-Next = temp->Next;
40         free(temp);
41     }
42 }

  我们发现上面有个 FindPrevious 函数用来找到当前元素的上一个元素,这个函数的出现是我们之前没预料到的。然而在删除操作当中我们发现需要这样一个函数,所以我们也声明这样一个函数,先不去考虑它的具体实现(这就是抽象)。事实上它的实现也是很简单的,不过我们会想到,既然可以用指针保存下一个结点,那为什么不用一个指针保存上一个结点呢?于是,双向链表就这么诞生了。

1 struct Node{
2     ElementType Element;
3     struct Node * Next;
4     struct Node * Prev;
5 };

  现在删除操作可以这样:

1 P->Prev->Next = P->Next; //P是指向要删除结点的指针
2 p->Next->Prev = P->Prev;
3 free(P);

  当链表的头尾相连时,这个链表就成了循环链表。在C#当中有个 LinkedList 类实现了 双向循环链表 ,文档和源码可以看这里这里。真是壮哉我大微软,文档资料应有尽有。

  写到这里,应该算写完了吧。还是没有达到下笔如有神的状态,我想应该是和分享的对象有关系。这文章要给哪一类读者看呢?其实是给我自己看的,那就这样吧,这一系列文章将纯粹是我为了总结而作的记录,没有读者对象。坑已经给自己挖了,后面还有很多较深的知识点,我会填坑的。

  下一篇应该是“栈”,而且我会讲解一个栈的实例。

(完)

  

时间: 2024-08-10 15:29:41

数据结构与算法分析—— 1、链表的相关文章

数据结构与算法分析 - 1 - 链表ADT

1.描述:不连续存储的表,可以把链表看成一个数组,数组元素是一个个结构体,这些结构体之间通过指针连接 2.优点: 利用不连续的存储空间,提高内存使用效率 避免删除和插入的线性开销 对比数组,大小不固定,可以扩展 3. 缺点:查找效率低 4. 定义一个单向链表 1 struct Node 2 { 3 ElementType value; 4 Node *next; //next指针,指向下一个节点 5 }; 5.检测链表是否为空 对于一个单向链表,链表为空即头节点为空 1 int IsEmpty(

《数据结构与算法分析》学习笔记(三)——链表ADT

今天简单学习了下链表,待后续,会附上一些简单经典的题目的解析作为学习的巩固 首先要了解链表,链表其实就是由一个个结点构成的,然后每一个结点含有一个数据域和一个指针域,数据域用来存放数据,而指针域则用来存放下一个结点的地址. 1.先给出结点的定义. typedef struct Node *PtrToNode; typedef PtrToNode List; typedef PtrToNode Position; struct Node { ElementType Element; Positio

数据结构学习——栈的链表实现(程序化)

关于栈的基本概念以及和Catalan数的关系,可以参见我的其他文章 参考资料<数据结构与算法分析--C语言描述> #include<stdio.h> #include<stdlib.h> /*栈的链表实现*/ typedef struct StackNode { struct StackNode *next; int data; }StackNode,*Stack; Stack CreateStack(void);//创建一个空栈 void MakeEmpty(Stac

数据结构1:数据结构和算法分析

问题引出 假设有一道题目:有一组N个数而要确定其中第k个最大者,我们称之为选择问题,那么这个程序如何编写?最直观地,至少有两种思路: 1.将N个数读入一个数组中,再通过某种简单的算法,比如冒泡排序法,以递减顺序将数组排序,则第k个位置上的元素就是我们需要的元素 2.稍微好一些的做法,将k个元素读入数组并以递减顺序排序,接着将接下来的元素再逐个读入,当新元素被读到时,如果它小于数组中的第k个元素则忽略之,否则将其放到数组中正确的位置上,同时将数组中的一个元素挤出数组,当算法终止时,位于第k个位置上

《数据结构与算法分析—C语言描述》pdf

下载地址:网盘下载 内容简介 编辑 <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行时间分析的基础上考查了一些高级数据结构,从历史的角度和近年的进展对数据结构的活跃领域进行了简要的概括.由于<数据结构与算法分析:C语言描述(原书第2版)>选材新颖,方法实用,题例丰富,取舍得当.<数据结构与算法分析:C语言描述(原书第2版)>的目的是培养学生良好的程序设计技巧和熟练的算

数据结构和算法分析

转自[五月的仓颉] http://www.cnblogs.com/xrq730/p/5122436.html 数据结构 数据结构是计算机存储.组织数据的方式,是指数据相互之间存在一种或多种特定关系的数据元素的集合.通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率(这就是为什么我们要研究数据结构的原因),数据结构往往同高效的检索算法和索引技术相关. 常见的数据结构有数组.栈.队列.链表.树.散列等,这些数据结构将是本数据结构的分类中重点研究的对象. 算法分析 算法是为求解一个问题需要遵

数据结构之利用单向链表实现多项式加法和乘法

在<数据结构与算法分析--c语言描述>一书中,作者指出了使用单向链表作为实现多项式的方法.但是没有给出具体实现.下面自己对其进行实现.只考虑功能.对其他细节不暂时不考虑.程序完成两个功能,使用单向链表完成多项式的加法和乘法.首先看加法,解决加法问题的思想在于对表示进行操作的两个链表表示的多项式按照指数递减的结构排列,每个节点的数据域存储着多项式某一项的系数(Coefficient)和指数(Exponent),还有一个指向后继节点的指针.节点的实现如下: 1 typedef struct Nod

《数据结构与算法分析》学习笔记(四)——栈ADT

一.栈ADT是what? 1.定义 栈,是限制插入和删除都只能在一个位置上进行的表. 2.图示 3.栈的基本功能 (1)是否为空 (2)进栈 (3)出栈 (4)清空 (5)取栈顶 二.栈的链表实现 <数据结构与算法分析>学习笔记(四)--栈ADT

数据结构与算法分析-栈

数据结构与算法分析-栈(单链表实现) //by xiabodan #include <stdio.h> #include <stdlib.h> typedef int elementtype; typedef struct node *stack; typedef struct node *position; struct node { elementtype data; position next; }; int isempty(stack S); void delete_sta

数据结构与算法分析-队列

数据结构与算法分析-队列(单链表实现) #include <stdio.h> #include <stdlib.h> typedef int elementtype; typedef struct headnode *queue; typedef struct node *position; struct node { elementtype data; position next; }; struct headnode{ int size; position front; pos