您的位置:首页 > 理论基础 > 数据结构算法

数据结构——循环单链表和双向链表

2016-03-25 21:57 615 查看

1.循环单链表

1.循环单链表特点:

链表中最后一个结点的指针域不再是结束标志,而是指向整个链表的第一个结点,从而使链表形成一个环。和单链表相同,循环单链表也有带头结点和不带头结点两种。带头结点的循环单链表实现插入和删除操作较为方便,且更加适用。

2. 单链表与循环单链表比较:

循环单链表可以从尾到头,而单链表不能从尾到头。因此处理的数据序列具有环形结构特点时,适合采用循环单链表。

3. 带头结点的循环单链表和带头结点的单链表比较:

①在初始化函数中,把语句( * head)->next=NULL改为( * head)->next=* head,即形成一个环

②在其他函数中,循环判断条件p->next!=NULL和p->next->next!=NULL中的NULL改成头指针head。

2.双向链表

双向链表特点:

每个节点除了有后继指针域还有一个前驱指针域。

双向链表的分类:

双向链表有:带头结点和不带头结点的双向链表(但是带头结点的双向链表更为常用)。也有循环和非循环之分,循环结构的双向链表更为常用。因此下面讨论的是带头结点的循环双链表

双向循环链表结点的结构体定义

typedef struct Node
{
DataType data;
struct Node *next;
struct Node *prior;
}DLNode;


data域、next域、prior域。其中data域是数据域,next域为指向后继结点的指针域,prior域为指向前驱结点的指针域。

双向链表的优点:

在单链中查找当前结点的后继结点并不困难,可以通过当前结点的next指针进行,但要查找当前结点的前驱结点,就要从头指针head开始重新进行。对于一个要频繁进行当前结点的后继结点和前驱结点的应用来说,使用双向链表很有效。

3.双向循环链表的实现

在双向链表中,有如下指针关系:设指针p指向双向循环链表中的第i个位置,则p->next指向i+1个结点。p->next->prior仍指向第i个结点,即p->next->prior==p;同样p->prior指向第i-1个结点,p->prior->next仍指向第i个结点,即p->prior->next==p;双向循环链表关系算法可以方便算法设计。

初始化

void ListInitiate(DLNode **head)
{
*head=(DLNode *)malloc(sizeof(SLNode));
(*head)->prior=*head;     //构成前驱指针循环链表
(*head)->next=*head;      //构成后继指针循环链表
}


插入数据元素

int ListInsert(DLNode *head,int i,DataType x)//在带头结点的双向循环链表head的第i个结点前,插入一个存放       //数据元素x的结点,插入成功返回1,失败返回0
{
DLNode *p,*q
int j;
p=head->next;
j=0;
while(p!=head&&j<i)
{
p=p->next;
j++;
}

if(j!=i)
{
printf("参数i错误!");
return 0;
}

s=(DLNode*)malloc(sizeof(SLNode));
s->data=x;
s->prior=p->prior;    //新结点指向前一个结点(中——>前)
p->prior->next=s;     //新结点结点指向前一个结点(前->中)
s->next=p;           //新节点指向后结点    (中->后)
p->prior=s;          //后结点指向新节点    (后->中)
return 1;
}


和单链表相比,双向循环链表的插入算法指针p可以直接指在第i个结点上,而不需要让指针p指在i-1上

删除数据元素

int ListInitiate(DLNode *head,int i,DataType *x)
{
DlNode *p;
int j;
p=head->next;
j=0
}
if(j!=i)
{
printf("删除数据元素为值参数出错!");
return 0;
}

*x=p->data;
p->prior->next=p->next;
p->next-prior=p->prior;
free(p);
return 1;


求当前数据元素个数ListLength(DLNode *head)

int ListLength(SLNode *head)
{
DLNode *p=head;
int size=0;
while(p->next!=NULL)
{
p=p->next;
size++;
}
return szie;
}


撤销内存空间Destroy(DLNode **head)

void Destory(DLNode **head)
{
DLNode *p,*q;
int i,n=ListLength(*head);
p=*head;
for(i=0;i<=n;i++)
{
q=p;
p=p->next;
free(p);
}
*head=NULL;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: