目录
2.3.1 线性表的链式存储—链表
线性表中每个结点有唯一的前驱结点和前驱结点。
设计链式存储结构时,每个逻辑结点存储单独存储,为了表示逻辑关系,增加指针域。
单链表中结点类型LinkNode的定义如下:
typedef struct LNode //定义单链表结点类型
{ ElemType data;
struct LNode *next; //指向后继结点
} LinkNode;
2.3.2 单链表
//插入操作语句描述如下:
s->next = p->next;
p->next = s;
//删除操作语句描述如下:
p->next = p->next->next;
void CreateListF(LinkNode *&L,ElemType a[],int n)
{ LinkNode *s;
int i;
L=(LinkNode *)malloc(sizeof(LinkNode));
L->next=NULL; //创建头结点,其next域置为NULL
for (i=0;i<n;i++) //循环建立数据结点
{ s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=a[i]; //创建数据结点s
s->next=L->next; //将s插在原开始结点之前,头结点之后
L->next=s;
}
}
void CreateListR(LinkNode *&L,ElemType a[],int n)
{ LinkNode *s,*r;
int i;
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
r=L; //r始终指向尾结点,开始时指向头结点
for (i=0;i<n;i++) //循环建立数据结点
{ s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=a[i]; //创建数据结点s
r->next=s; //将s插入r之后
r=s;
}
r->next=NULL; //尾结点next域置为NULL
}
(1)初始化线性表InitList(L) 建立一个空的单链表,即创建一个头结点。
void InitList(LinkNode *&L)
{
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next=NULL;
}
(2)销毁线性表DestroyList(L) 释放单链表L占用的内存空间。即逐一释放全部结点的空间。
void DestroyList(LinkNode *&L)
{
LinkNode *pre=L, *p=L->next; //pre指向p的前驱结点
while (p!=NULL) //扫描单链表L
{ free(pre); //释放pre结点
pre=p; //pre、p同步后移一个结点
p=pre->next;
}
free(pre); //循环结束时,p为NULL,pre指向尾结点,释放它
}
(3)判线性表是否为空表ListEmpty(L) 若单链表L没有数据结点,则返回真,否则返回假。
bool ListEmpty(LinkNode *L)
{
return(L->next==NULL);
}
(4)求线性表的长度ListLength(L) 返回单链表L中数据结点的个数。
int ListLength(LinkNode *L)
{
int n=0;
LinkNode *p=L; //p指向头结点,n置为0(即头结点的序号为0)
while (p->next!=NULL)
{ n++;
p=p->next;
}
return(n); //循环结束,p指向尾结点,其序号n为结点个数
}
(5)输出线性表DispList(L) 逐一扫描单链表L的每个数据结点,并显示各结点的data域值。
void DispList(LinkNode *L)
{
LinkNode *p=L->next; //p指向开始结点
while (p!=NULL) //p不为NULL,输出p结点的data域
{ printf("%d ",p->data);
p=p->next; //p移向下一个结点
}
printf("\n");
}
(6)求线性表L中位置i的数据元素GetElem(L,i,&e) 在单链表L中从头开始找到第i个结点,若存在第i个数据结点,则将其data域值赋给变量e。
bool GetElem(LinkNode *L,int i,ElemType &e)
{
int j=0;
LinkNode *p=L; //p指向头结点,j置为0(即头结点的序号为0)
while (j<i && p!=NULL)
{ j++;
p=p->next;
}
if (p==NULL) //不存在第i个数据结点,返回false
return false;
else //存在第i个数据结点,返回true
{ e=p->data;
return true;
}
}
(7)按元素值查找LocateElem(L,e) 在单链表L中从头开始找第一个值域与e相等的结点,若存在这样的结点,则返回位置,否则返回0。
int LocateElem(LinkNode *L,ElemType e)
{
int i=1;
LinkNode *p=L->next; //p指向开始结点,i置为1
while (p!=NULL && p->data!=e)
{ p=p->next; //查找data值为e的结点,其序号为i
i++;
}
if (p==NULL) //不存在元素值为e的结点,返回0
return 0;
else //存在元素值为e的结点,返回其逻辑序号i
return i;
}
(8)插入数据元素ListInsert(&L,i,e) 先在单链表L中找到第i-1个结点p,若存在这样的结点,将值为e的结点s插入到其后。
bool ListInsert(LinkNode *&L,int i,ElemType e)
{ int j=0;
LinkNode *p=L,*s; //p指向头结点,j置为0
while (j<i-1 && p!=NULL)
{ j++;
p=p->next;
}
if (p==NULL) //未找到第i-1个结点,返回false
return false;
else //找到第i-1个结点p,插入并返回true
{
s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=e; //创建新结点s,其data域置为e
s->next=p->next; //将s插入到p之后
p->next=s;
return true;
}
}
(9)删除数据元素ListDelete(&L,i,&e) 先在单链表L中找到第i-1个结点p,若存在这样的结点,且也存在后继结点,则删除该后继结点。
bool ListDelete(LinkNode *&L,int i,ElemType &e)
{ int j=0;
LinkNode *p=L,*q; //p指向头结点,j置为0
while (j<i-1 && p!=NULL) //查找第i-1个结点
{ j++;
p=p->next;
}
if (p==NULL) //未找到第i-1个结点,返回false
return false;
else //找到第i-1个结点p
{ q=p->next; //q指向第i个结点
if (q==NULL) //若不存在第i个结点,返回false
return false;
e=q->data;
p->next=q->next; //从单链表中删除q结点
free(q); //释放q结点
return true; //返回true表示成功删除第i个结点
}
}