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

#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 ;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 算法change(p)的步骤如下: 1. 如果p为空或者p的结点为空,则直接返回。 2. 定义一个临时变量temp,将p的结点赋值给temp。 3. 将p的结点结点的next指针指向p。 4. 将p的next指针指向temp。 5. 将p的结点的next指针指向p的next指针所指向结点。 6. 如果p的next指针不为空,则将p的next指针所指向结点的prior指针指向p的结点。 7. 如果p的结点的prior指针不为空,则将p的结点的prior指针指向p。 8. 返回。 ### 回答2: 算法change(p)的实现步骤如下: 1. 首先判断p是否为空,若为空则返回。 2. 判断p所指向结点是否为链表的头结点,若是则返回。 3. 定义两个指针q和r,分别指向p的结点和p所指向结点。 4. 将p的结点的next指针指向p的下一个结点,保证链表的连续性。 5. 将p的结点赋值给p所指向结点的prior指针,保证链表双向性。 6. 将p所指向结点赋值给p的结点的next指针,保证链表双向性。 7. 将p所指向结点的next指针指向p的结点,保证链表双向性。 8. 将p的next指针指向p所指向结点的next指针,保证链表的连续性。 9. 将p所指向结点的next指针赋值给p所指向结点的prior指针,保证链表双向性。 10. 将p所指向结点赋值给p所指向结点的next指针的结点,保证链表双向性。 11. 返回链表。 该算法的时间复杂度为O(1),对于双向循环链表,只需要进行常数次的操作即可完成结点和其结点交换。 ### 回答3: 算法change(p)的实现思路如下: 1. 判断p是否为空指针或p所指向结点是否为链表的头结点,如果满足条件,则无法交换,直接返回。 2. 获取p所指向结点结点pre和后继结点next,分别通过p->prior和p->next指针获取。 3. 如果pre为头结点,则将链表的头结点修改为p所指向结点。 4. 将p所指向结点与pre结点结点pre_prev连接。 5. 将p所指向结点与其后继结点next连接。 6. 将pre_prev结点与p所指向结点连接。 7. 将p所指向结点结点修改为pre_prev。 8. 将p所指向结点的后继结点修改为pre。 9. 返回修改后的链表。 具体的算法实现如下: ```cpp void change(Node *p) { if (p == NULL || p->prior == NULL) { return; // 无法交换,直接返回 } Node *pre = p->prior; Node *next = p->next; if (pre == head) { head = p; // 若pre为头结点,则修改头结点 } Node *pre_prev = pre->prior; pre_prev->next = p; p->prev = pre_prev; p->next = pre; pre->prev = p; pre->next = next; if (next != NULL) { next->prev = pre; } } ``` 以上是算法change(p)的具体实现,核心思想是通过调整各个结点之间的连接关系实现结点交换。该算法的时间复杂度为O(1)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值