1. 引言
本文主要讲解一个线性表 (应用举例)
2. 具有实际意义的线性链表
#include "ds.h"
using namespace std;
typedef int ElemType;
// 结点类型
typedef struct LNode{
ElemType data;
struct LNode *next;
}*Link,*Position;
typedef struct LinkList{
Link head, tail; // 分别指向线性链表中的头结点和最后一个结点
int len; // 指示线性链表中数据元素的个数
}LinkList;
void MakeNode(Link &p, ElemType e);
void FreeNode(Link &p);
void InitList(LinkList &L);
void ClearList(LinkList &L);
void DestroyList(LinkList &L);
// h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前, 形参增加L,因为需修改L
void InsFirst(LinkList &L,Link h,Link s);
// h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。
// 若链表为空(h指向尾结点),q=NULL,返回FALSE
Status DelFirst(LinkList &L, Link h, Link &q);
// 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的
// 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
void Append(LinkList &L, Link s);
// 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置。若无前驱,则返回NULL
Position PriorPos(LinkList L, Link p);
// 删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Status Remove(LinkList &L, Link &q);
// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
// 并修改指针p指向新插入的结点
void InsBefore(LinkList &L, Link &p, Link s);
// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
// 并修改指针p指向新插入的结点
void InsAfter(LinkList &L,Link &p,Link s);
// 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
void SetCurElem(Link p, ElemType e);
ElemType GetCurElem(Link p);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Position GetHead(LinkList L);
Position GetLast(LinkList L);
Position NextPos(Link p);
// 返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR。i=0为头结点
Status LocatePos(LinkList L, int i, Link &p);
// 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
// 若不存在这样的元素,则返回NULL
Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
void ListTraverse(LinkList L, void(*visit)(ElemType) );
// 已知L为有序线性链表,将元素e按非降序插入在L中。
void OrderInsert(LinkList &L, ElemType e, int (*com)(ElemType, ElemType));
// 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中
// 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数
// compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
Status LocateElem(LinkList L,ElemType e,Position &q,int(*compare)(ElemType,ElemType));
// 分配由p指向的值为e的结点。若分配失败,则退出
void MakeNode(Link &p, ElemType e)
{
p = (Link)malloc(sizeof(LNode));
if (!p)
exit(ERROR);
memcpy(&(p->data), &e, sizeof(ElemType));
}
// 释放p所指结点
void FreeNode(Link &p)
{
free(p);
p = NULL;
}
// 构造一个空的线性链表L
void InitList(LinkList &L)
{
Link p;
p = (Link)malloc(sizeof(LNode)); // 生成头结点
if (p)
{
p->next = NULL;
L.head = L.tail = p;
L.len = 0;
}
else
exit(ERROR);
}
// 将线性链表L重置为空表,并释放原链表的结点空间
void ClearList(LinkList &L)
{
Link p, q;
if (L.head != L.tail)
{
p = q = L.head->next;
L.head->next = NULL;
while (p != L.tail)
{
q = p->next;
free(p);
p = q;
}
free(q); // 释放尾节点
L.tail = L.head;
L.len = 0;
}
}
// 销毁线性链表L,L不再存在
void DestroyList(LinkList &L)
{
ClearList(L);
FreeNode(L.head);
L.tail = NULL;
L.len = 0;
}
// h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前, 形参增加L,因为需修改L
void InsFirst(LinkList &L,Link h,Link s)
{
s->next = h->next;
h->next = s;
if (h == L.tail)
L.tail = s;
L.len++;
}
// h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。
// 若链表为空(h指向尾结点),q=NULL,返回FALSE
Status DelFirst(LinkList &L, Link h, Link &q)
{
q = h->next;
if (q) // 链表非空
{
h->next = q->next;
if(!h->next) // 删除尾结点
L.tail = h; // 修改尾指针
L.len--;
r