链表数据结构和算法实现
链表是一种线性表的链式表示和实现,定义线性表节点的结构。链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构。一个链表有很多个节点,各个节点之间通过指针连接起来,所以各个节点之间的位置可以不连续,也就是可以放在不同的位置,所以在空间上可以是不连续的。
链表中的每一个内存块被称为节点Node。节点除了存储数据外,还需记录链上下一个节点的地址,即后继指针next。每个节点包括两个域:其中存储数据元素的域称为数据域,存储直接侯冀存储位置的域称为指针域。指针域存储的信息称作指针或链。
单链表可以由头指针唯一确定,在C语言中可以用“结构指针”来描述。单链表的存储结构可以用typedef struct LNode { ElemType data ; struct LNode *next; }LNode ,*LinkList;来定义,其中LinkList为指向结构体LNode的指针类型。
为了提高程序的可读性,在此对同一个结构体指针类型起了两个名称,LinkList与LNode*,两者本质上是相等的,通常习惯用LinkList定义单链表,强调定义某个单链表的头指针;用LNode*定义指向单链表的任意节点的指针变量。
下面对首元节点、头结点、头指针三个容易混淆的概念加以说明:
1. 首元节点是指链表中存储第一个数据元素a1的节点。
2. 头结点是在首元节点前面的预设的节点,其指针域指向首元节点。头结点的数据域可以不存储任何数据元素,也可以存储与数据元素类型相同的其他附加信息。
3. 头指针是指向链表中第一个节点的指针。若链表没有头结点,则头指针所指向的节点为线性表的头结点;若链表不设头结点,则头指针所指向的节点为该线性表的首元节点。
单链表的基本操作的实现:
1、单链表的初始化:单链表的初始化可以用Status InitList (LinkList &L ) { L = new LNode ; L->next = Null; return OK;}来实现。
2、单链表的取值:单链表的取值可以用Statua GetElem (LinkList L,int i ,ElemType &e) { ... }来实现,其中p指向首元节点,j初始值记为1,顺序向后遍历,直到p为空或者p指向第i个元素。
3、单链表的按值查找:单链表的按值查找可以用LNode *LocateElem (LinkList L,ElemType e) { ... }来实现,其中p指向首元节点,顺着链域向后扫描,直到p为空或者p所指向的节点的数据域等于e。
单链表的其他操作还包括单链表的插入、删除、遍历等。单链表的插入可以用void ListInsert (LinkList &L,int i,ElemType e) { ... }来实现,其中p指向首元节点,顺序向后遍历,直到p指向第i个元素,然后插入新的节点。
单链表的删除可以用Status ListDelete (LinkList &L,int i) { ... }来实现,其中p指向首元节点,顺序向后遍历,直到p指向第i个元素,然后删除该节点。
单链表的遍历可以用void ListTraverse (LinkList L,void (*visit)(ElemType)) { ... }来实现,其中p指向首元节点,顺序向后遍历,直到p为空,然后对每个节点调用visit函数。
链表是一种常用的数据结构,它可以用来解决许多实际问题。单链表是链表的一种特殊形式,它的实现可以使用C语言来描述。单链表的基本操作包括初始化、取值、按值查找、插入、删除、遍历等。