2.4其他形式的链表
2.4.1单向循环链表
在单向链表的基础上,在其最后一个结点的指针域中将空指针改为指向头结点的指针,此即为单项循环链表。
常用的单项循环链表有两种,一种是带头指针的单项循环链表,另一种是带尾指针的单项循环链表。
带头指针的单项循环链表判断为空的条件:L->next == L
带尾指针的单项循环链表的判断为空的标志是:R->next == R
如果有两个带尾指针的单向循环链表进行连接的话需要进行四步运算:
//R1为第一个链表的指针,R2为第二个链表的指针
1.p = R1->next;q=R2->next;
2.R1->next = R2->next->next;
3.R2->next = p;
4.free(q);
在进行单向循环链表的操作时,唯一不同的是需要进行是否为空的判断,下面是单向循环链表的操作
1.初始化
创建带有头结点的单向循环链表,即让头结点的指针域记住自己(因为在最开始创建的时候只有一个结点,所以头指针的尾结点需要需要指向自己)。
int initCirLink(LinkList *L){
*L = (LinkList)malloc(sizeof(Node));
if(*L == NUll)
exit(0);
(*L)->next = *L;
return 1;
}
2.插入
根据插入位置i,将指定数据元素插入到第i-1和第i个结点之间。
//pos用来判断是否到了最后一个,判断插入位置的异常。
int insertCirLink(LinkList L,int i,ElemType x){
LinkList p=L;
int pos=0;
while(p->next != L&&pos<i-1){
p=p->next;
pos++;
}
if(p->next == L && pos < i-1||pos>i-1){
printf("插入位置异常\n");
return 0;
}
s=(LinkList)malloc(Lnode);
s->data = x;
s->next = p->next;
p->next = s;
return 1;
}
3.删除
根据删除位置i,将第i-1个结点的后继结点置为第i+1个结点,并释放第i+1个结点的空间。
int delCirLink(LinkList L,int i,ElemType x){
LinkList p=L;
int pos=0;
while(p->next != L&&pos<i-1){
p=p->next;
pos++;
}
if(p->next == L && pos < i-1||pos>i-1){
printf("位置异常或链表为空\n");
return 0;
}
q = p->next;
*x = q->data;
p->next = q->next;
delete q;
return 1;
}
2.4.2双向循环链表
单项链表不便于查找前驱结点,所以为了方便两个方向的查询,可以在结点设两个指针域,一个存放前驱结点的地址,另一个存放直接后继结点的地址。
数据类型描述
typedef struct Donde{
ElemType data;
struct Donde *pre;//存放前驱结点的地址
struct Donde *next;//存放后继结点的地址
}Donde,*DLinkList;
1.初始化操作
创建一个带有头结点的空链表。
int initDLinkList(DLinkList *L){
*L = (DLinkList)malloc(sizeof(Dnode));
if(*L == NUll)
exit(0);
(*L)->pre = (*L)->next = *L;
return 1;
}
2.插入
按后继方向根据指定位置插入结点。
int insertDLinkList(DLinkList L,int i,ElemType x){
DLinkList p=L,s;
int j;
//p指向第i-1个结点,j记结点的位置
p=L;
j=0;
while(p->next != L && j<i-1){
p=p->next;
j++;
}
if(p->next == L&&j<i-1||j>i-1){
printf("插入位置不合理\n");
return 0;
}
s=(DlinkList)malloc(sizeof(Dnode));
s->data = x;
s->pre = p;
s->next = p->next;
p->next->pre = s;
p->next = s;
return 1;
}
3.删除操作
按后继方向根据指定位置删除结点。
int deleteDLinkList(DlinkList L,int i,ElemType *x){
DLinkList p=L,s;
int j;
//p指向第i-1个结点,j记结点的位置
p=L;
j=0;
while(p->next != L && j<i-1){
p=p->next;
j++;
}
if(p->next == L&&j>i-1){
printf("删除位置不合理或链表为空\n");
return 0;
}
q = p->next;
*x = q->data;
p->next = q->next;
q->next->pre = p;
free(q);
return 1;
}
4.遍历
指定遍历方向,显示所有数据。
void dispDlinkList(DLinkList L,int n){
DLinkList p;
if(1==n){
p=L->next;
while(p!=L){
printf(p->data);
p=p->next;
}
printf("\n");
}
if(2==n){
p=L->pre;
while(p!=L){
printf(p->data);
p=p->pre;
}
printf("\n");
}
}