四、循环链表和双向链表

循环链表

循环链表是链式存储结构的另一种形式,特点是单链表的最后一个结点(终端结点)的指针域不为空,而是指向链表的头结点,使整个链表形成一个环。

在这里插入图片描述

例子:

/*
    将值为x的新结点插入到从大到小有序循环链表的适当位置
*/
int InsertData(LinkList head,int x){
    ListNode *s,*p,*q;      //s新结点  q当前结点(即插入新节点s的后继结点)  p插入位置的前趋节点
    s = (ListNode *)malloc(sizeof(ListNode));   //申请结点存储空间
    s->data = x;    p = head;
    q = p->next;                    //q指向开始结点
    while (q->data > x && q != head)   //查找插入位置
    {
        p = p->next;                //p指向q的前趋结点
        q = p->next;                //q指向当前结点
    }
    p->next = s;    //插入s结点
    s->next = q;
}
双向链表

在单链表的结点类型中增加一个指向其直接前驱的指针域prior,这样形成的链表中有两条不同方向的链,称为双向链表。

在这里插入图片描述
上图终端结点又指向头结点,因此称作双向循环链表

双向链表结构如下:
typedef int DataType; 
typedef struct dlnote
{
    DataType data;
    struct dlnote *prior, *next;
}DLNote;
typedef DLNote * DLinkList;
DLinkList head;
双向链表的插入与删除
/*
    将值得x的新结点插入到带头结点的双向链表中指定结点*p之前
*/
void DLInsert(DLNote *p,DataType x){
    DLNote *s = (DLNote *)malloc(sizeof(DLNote));   //申请新结点
    s->data = x;
    s->prior = p->prior;s->next = p;
    p->prior->next = s;  //p的直接前驱结点指向s
    p->prior=s;          
}

/*
    删除带头结点的双向链表中指定结点P
 */
DataType DLDelete(DLNote *p){
    p->prior->next = p->next;
    p->next->prior = p->prior;
    DataType x = p->data;
    free(p);
    return x;
}

例子

假设有一个头结点指针为head的循环双向链表,其结点类型包括三个域:prior、data、next。但是其指向前趋结点的指针域prior为空,因此该双向链表其实是一个单循环链表。试写一算法,将其修改为真正的双循环链表。

void trans(DLinkList head){
	DLNode *p;
	p = head;
	while(p->next != head){
		p->next->prior=p;
		p=p->next;
	}
	head -> prior = p;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值