已知 p 指向双向循环链表中的一个结点,其结点结构为 data、llink、rlink 三个域,写出算法 change(p),交换 p 所指向的结点和它的前缀结点的顺序(就是把p的前一个结点和后一个

博客围绕数据结构展开,重点提及链表和算法。链表是数据结构的重要组成部分,算法则用于对链表等数据结构进行操作和处理,二者在信息技术领域有重要作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>

struct SLB
{
	int data;
	struct SLB *link,*rlink;
};

struct SLB *Create();
void Shu(struct SLB *head);
struct SLB *Change(struct SLB *head);

int main()
{
	struct SLB *Shuang;
	printf("请输入链表结点元素(输入-1回车结束输入):\n");
	Shuang=Create();
	printf("双链表创建结果如下:\n");
	Shu(Shuang);
	Shuang=Change(Shuang);
	printf("交换结点顺序后链表元素排列如下:\n");
	Shu(Shuang);
	return 0;
}

struct SLB *Create()    //创建双链表,我觉得跟单链表区别不太大
{
	struct SLB *head=NULL,*p,*p1;
	p=(struct SLB *)malloc(sizeof(struct SLB));
	scanf("%d",&p->data );
	p->link =NULL;
	p->rlink =NULL;
	while(p->data !=-1)
	{
		if(head==NULL)
		{
			head=p;
			p1=p;
		}
		else
		{
			p1->rlink =p;
			p->link =p1;
			p1=p;
		}
		p=(struct SLB *)malloc(sizeof(struct SLB));
	    scanf("%d",&p->data );
	    p->link =NULL;
	    p->rlink =NULL;
	}
	return head;
}

void Shu(struct SLB *head)
{
	struct SLB *p;
	p=head;
	while(p!=NULL)
	{
		printf("%-3d",p->data );
		p=p->rlink ;
	}
	putchar('\n');
}

struct SLB *Change(struct SLB *head)
{
	struct SLB *p,*L,*temp;
	L=(struct SLB *)malloc(sizeof(struct SLB));   //这里我设置了头结点,这样交换头结点的时候也好返回
	L->link =NULL;
	L->rlink =head;

	p=head;
	int n;
	printf("请输入要改变第几个结点的前后结点位置(大于1小于6):");    //这里要是严谨一点的话可以遍历看用户输入了多
	                                                                            //少结点,然后告诉用户要输入在这个范围内的数字,因为我们这题主要是交换,所以就不整
	scanf("%d",&n);
	int j=1;
	while(j<n&&p!=NULL)
	{
		j++;
		p=p->rlink ;
	}

    //链表结点交换类的题,不太熟悉的话多画图品一下,把它们的指针画一下该如何指,切记一定不要出现断开链表从而找不到它的前驱或者后驱结点
	//比如有p1->p->p2,若你没有标记p2结点,但是你的p->next指向了别处或者为空,那么你就会出现找不到p2结点以及之后的链表了,也就是断开联系了,
	//最好就是不要断开,如果不得已可以标志一下以防找不到,比如我下面的temp指针就是拿来标志的


	//画图理解起来真的vividly,不然你可能觉得怎么指过去指过来脑子就晕了

	//下面这几种指法我觉得可以合并,就是那种不一样的条件就区别一下,因为第一次交换双链表结点,我刚刚也看晕了,你们有空自己试试简化一下吧
	if(n==2)  //即交换第二个结点的前后结点,因为所需的它的前驱的前驱结点为空,所以分开讨论,可能也有更简单的,因为第一次写双链表可能不那么熟悉,可以自己去试试改改
	{
		L->rlink =p->rlink ;
		p->rlink ->link =NULL;
		p->link  ->rlink =p->rlink ->rlink ;
		p->rlink ->rlink ->link =p->link ;
		p->rlink ->rlink =p;
		p->link ->link =p;
		temp=p->rlink ;
		p->rlink =p->link ;
		p->link =temp;
	}
	else if(n==5)//跟也是特殊结点,后驱的后驱结点位空
	{
		p->link ->link ->rlink =p->rlink ;
		p->rlink ->link =p->link ->link ;
		p->link ->rlink =NULL;
		p->link ->link =p;
		p->rlink ->rlink =p;
		temp=p->rlink ;
		p->rlink =p->link ;
		p->link =temp;
	}
	else
	{
	    p->link ->link ->rlink =p->rlink ;     //画图会好理解一些
	    p->rlink ->link =p->link ->link ;
	    p->link ->rlink =p->rlink ->rlink ;
	    p->rlink ->rlink ->link =p->link ;
	    p->rlink ->rlink =p;    //尤其下面这几个步骤,注意前后顺序!link一定是它的前驱结点,rlink是它的后继结点
	    p->link ->link =p; 
	    temp=p->rlink ;
	    p->rlink =p->link ;
	    p->link =temp;
	}
	return L->rlink ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值