链表进阶操作一:调换相邻节点的位置 以及 让节点所有奇偶位置互换(图文演示,通俗易懂)

关于链表有很多可以实现的操作,接下来讲讲一些关于链表的进阶操作。

我们先来讲讲相邻节点是如何调换的

一、先创建一条链表

直接上代码(不知道如何创建链表的同学可以看看我上一篇文章)

//需要的两个头文件
#include<stdio.h>
#include<stdlib.h>

//定义结构体(包含指针域和数据域)
typedef struct Node
{
	int data;
	struct Node *next;
 } Node;
 
 
 int main()
 {
 	Node *p1,*p2;      //定义两个指针进行各种操作(可看我的上一篇文章)
 	Node *head;       //定义head指针标记头结点

	int x; 	
 	head = NULL;
 	
 	
 	printf("请输入创建多少个链表:"); 
 	scanf("%d",&x);
 	
// 	创建链表节点并连接 
	for(int i=1;i<=x;i++)
 	{
 		p1 = (Node *)malloc(sizeof (Node));
 		if(head == NULL)
			{
		 		head = p1;
		 		p2 = p1;
			}
		else
		{
			p2->next =p1;
			p2 = p1;
		}
	}
	
	p2->next = NULL;    //把尾结点标记为NULL
	p = head;

此时该链表图为:

在这里插入图片描述

链表的顺序已经是固定的了。要想实现调换链表中临近节点的位置,如调换2和3节点,我们该如何做呢?如何用两个指针实现呢?

二、先试着调换第2、第3节点的位置

调换后的位置为1→3→2→4→…即我们需要把1节点指向3的位置,2节点指向4的位置,然后2,3节点反转一下,就实现了2,3节点调换。

操作如图:
在这里插入图片描述

貌似这图也不是很直观。。要是没看懂还是需要自己画图多想想,其实就是1→2→3→4变成1→3→2→4

直接上代码:

为方便理解,我们先定义三个指针*p,*p1,*p2分别指向1,23的位置
即:p = head;
	p1 = p->next;
	p2 = p1->next;
调换位置的操作:
	p->next = p2;                1指向3的位置
	p1->next = p2->next;         2指向4的位置
	p2->next = p1;               3又指向2的位置
	

三、输入输出数据,检测操作是否正确

输入数据
	int q=1;
	while (p != NULL)
	{
		p->data = q;
		q++;
		printf("%d ",p->data);
		p = p->next;
	 } 
	
	printf("\n");
输出数据:
	p = head;
	
	while (p != NULL)
	{
		printf("%d ",p->data);
		p = p->next;
	 } 

运行结果:


请输入创建多少个链表:4
1 2 3 4
1 3 2 4
--------------------------------
Process exited after 4.014 seconds with return value 0
请按任意键继续. . .

调换2,3位置的操作成功了

如何实现链表中所有节点奇数和偶数的位置互换呢?

这是室友的一道题,大概就是实现1和2的位置互换,3和4的位置互换,我研究了半小时,想发出来给大家分享一下想法。

讲讲我的思路

其实就是我刚刚讲的那个相邻位置互换的进阶操作。多加一个循环来实现就可以。定义三个指针的好处就是,p指针来标记位置,p1和p2用来实现调换位置的功能。

由于上面所讲可以看出,要想调换两个节点的位置,我们至少需要知道调换节点的前一个的位置。也就是说,要想调换2,3节点的位置,必须要知道1节点的位置,否则,1节点无法指向3节点的位置致使操作失败。

注意:只要调换1,2节点的位置时不需要标记前一个节点的位置,所以我们要进行特殊化处理(先调换这两个的位置)

一、先调换1,2节点的位置

代码如下: 
	p1=head;                 p1指向1 节点的位置 
 	p2=head->next;           p2指向2 节点的位置
 	
 			
	head=p2;                 因为2节点要变成头结点,所以p2标记为head
 	p1->next = p2->next;     1指向3
 	p2->next = p1;           2指向1

	已经完成了1,2节点位置的调换

二、设计循环 调换之后节点的位置

我们发现,p节点需要标记偶数节点的位置。即,调换3,4要标记2节点,调换5,6要标记4节点。

由于始终为p1从奇数变为偶数。所以只需要在调换完成后用p来标记p1的位置即可。

直接上代码:

调换:

p = p1;                              标记上一次调换完成后p1的位置


for(a=1;a<=(x/2)-1;a++)              for循环语句,由于已经调换了1,2,所以循环次数-1
{
	p1 = p->next;                    
	p2 = p1->next;                   p→p1→p2           
	
	p->next = p2;                   
	p1->next = p2->next;             进行调换奇数偶数节点的调换
	p2->next = p1;
	
	p=p1;                            标记调换完成后p1的位置
}

三、输出链表的数据,检测操作是否正确

代码如下:

	p = head;
	
	
	while(p != NULL)
	{
		printf("%d ",p->data);
		p = p->next;
	}
	

运行结果:


请输入创建多少个链表:9
反转前:1 2 3 4 5 6 7 8 9
反转后:2 1 4 3 6 5 8 7 9
--------------------------------
Process exited after 2.78 seconds with return value 0
请按任意键继续. . .

以后会不定时更新进阶操作的哦,希望大家可以点个赞,点个关注收藏~
大家有啥问题可以一起讨论哦,谢谢观看

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值