反转链表-迭代反转法

反转链表,又可以称为翻转或逆置链表,如图: 

 常用的实现方案有 4 种,这里分别将它们称为迭代反转法、递归反转法、就地逆置法和头插法。值得一提的是,递归反转法更适用于反转不带头节点的链表;其它 3 种方法既能反转不带头节点的链表,也能反转带头节点的链表。

1、迭代反转链表:

      (1)思想:从当前链表的首元节点开始,一直遍历至链表的最后一个节点,这期间会逐个改变所遍历到的节点的指针域,另其指向前一个节点。
      (2)实现:借助 3 个指针分别命名为 beg、mid、end。它们的初始指向如图 所示:

        

接下来只需改变 mid 所指节点的指向即可,不用修改 3 个指针的指向。 

最后只需改变头结点指针的指向,另其和 mid 同向,就实现了链表的反转。

 

代码片段:

//迭代反转链表
link* iteration_reverse(link* p){
	if(p==NULL||p->next==NULL||p->next->next==NULL){
		return p;
	}
	else{
		link* beg=NULL;
		link* mid=p->next;
		link* end=p->next->next;
		while(1){
			//修改mid所指结点的指向
			mid->next=beg;
			//此时判断end是否为NULL,成立则退出循环
			if(end==NULL){
				break;
			} 
			//三个指针整体向后移
			beg=mid;
			mid=end;
			end=end->next; 
		}
		//最后修改头指针指向
		p->next=mid; 
		return p;
	}
} 

完整代码: 

#include<stdio.h>
#include<stdlib.h>
//定义链表结点结构 
typedef struct Link{
	int elem;
	struct Link* next;
}link;
//定义链表初始化函数 
link* initLink(){
	int i=0;
	link* temp=NULL;
	link* p=(link*)malloc(sizeof(link));//创建头结点
	//头结点数据域为0 
	p->elem=0;
	p->next=NULL;
	temp=p;//头指针指向头结点
	for(i=1;i<5;i++){
		link* a=(link*)malloc(sizeof(link));
		a->elem=i;
		a->next=NULL;
		temp->next=a;//连接结点
		temp=a;//temp指针向后移动 
	} 
	return p; 
}
//定义打印链表数据函数
void printLink(link* p){
	link*t=p->next;//定义指针变量指向首元结点 
	while(t){
		printf("%d ",t->elem);
		t=t->next;
	}
	printf("\n");
}

//迭代反转链表
link* iteration_reverse(link* p){
	if(p==NULL||p->next==NULL||p->next->next==NULL){
		return p;
	}
	else{
		link* beg=NULL;
		link* mid=p->next;
		link* end=p->next->next;
		while(1){
			//修改mid所指结点的指向
			mid->next=beg;
			//此时判断end是否为NULL,成立则退出循环
			if(end==NULL){
				break;
			} 
			//三个指针整体向后移
			beg=mid;
			mid=end;
			end=end->next; 
		}
		//最后修改头指针指向
		p->next=mid; 
		return p;
	}
} 

int main()
{
	link* p=initLink();
	printf("原始链表:");
	printLink(p);
	printf("反转链表:"); 
	iteration_reverse(p);
	printLink(p);
	return 0;
}

输出结果:

若无头结点:

 

代码片段:

//迭代反转法,head 为无头节点链表的头指针
link * iteration_reverse(link* head) {
	if (head == NULL || head->next == NULL) {
		return head;
	}
	else {
		link * beg = NULL;
		link * mid = head;
		link * end = head->next;
		//一直遍历
		while (1)
		{
			//修改 mid 所指节点的指向
			mid->next = beg;
			//此时判断 end 是否为 NULL,如果成立则退出循环
			if (end == NULL) {
				break;
			}
			//整体向后移动 3 个指针
			beg = mid;
			mid = end;
			end = end->next;
		}
		//最后修改 head 头指针的指向
		head = mid;
		return head;
	}
}

完整代码:

#include <stdio.h>
#include <stdlib.h>
//链表中节点的结构
typedef struct Link {
	int  elem;
	struct Link *next;
}link;

link * initLink() {
	int i;
	link * p = NULL;//创建头指针
	link * temp = (link*)malloc(sizeof(link));//创建首元节点
	//首元节点先初始化
	temp->elem = 1;
	temp->next = NULL;
	p = temp;//头指针指向首元节点
	for (i = 2; i < 5; i++) {
		link *a = (link*)malloc(sizeof(link));
		a->elem = i;
		a->next = NULL;
		temp->next = a;
		temp = temp->next;
	}
	return p;
}
//迭代反转法,head 为无头节点链表的头指针
link * iteration_reverse(link* head) {
	if (head == NULL || head->next == NULL) {
		return head;
	}
	else {
		link * beg = NULL;
		link * mid = head;
		link * end = head->next;
		//一直遍历
		while (1)
		{
			//修改 mid 所指节点的指向
			mid->next = beg;
			//此时判断 end 是否为 NULL,如果成立则退出循环
			if (end == NULL) {
				break;
			}
			//整体向后移动 3 个指针
			beg = mid;
			mid = end;
			end = end->next;
		}
		//最后修改 head 头指针的指向
		head = mid;
		return head;
	}
}

void display(link *p) {
	link* temp = p;//将temp指针重新指向头结点
	//只要temp指针指向的结点的next不是Null,就执行输出语句。
	while (temp) {
		printf("%d ", temp->elem);
		temp = temp->next;
	}
	printf("\n");
}
int main() {
	link*p = NULL;
	//初始化链表(1,2,3,4)
	printf("初始链表为:\n");
	p = initLink();
	display(p);
	printf("反转链表为:\n");
	p = iteration_reverse(p);
	display(p);
	
	return 0;
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
反转链表中从位置 m 到 n 的部分,可以按以下步骤进行操作: 首先,找到第 m 个节点和第 n 个节点的位置。 然后,我们将从第 m 个节点到第 n 个节点的部分链表进行反转操作。 最后,将反转后的部分链表重新连接到原链表中。 下面是具体的算实现: 1. 声明一个 dummy 节点,并将其 next 指针指向头节点。同时声明 pre 指针指向 dummy 节点。 2. 将 pre 指针移动到第 m - 1 个节点的位置。 3. 声明一个 cur 指针指向 pre 指针的下一个节点。 4. 声明一个 tail 指针指向 cur 指针的下一个节点。 5. 从 m 到 n 的位置进行反转操作,需要进行 n - m 次迭代。 1. 将 cur 指针的 next 指针指向 tail 指针。 2. 将 pre 指针的 next 指针指向 cur 指针。 3. 将 cur 指针移动到 tail 指针的位置。 4. 将 tail 指针指向 cur 指针的下一个节点。 6. 将反转后的部分链表重新连接到原链表中,即将第 m - 1 个节点的 next 指针指向第 n 个节点。 7. 返回 dummy 节点的 next 指针。 以下是具体的实现代码: ```python def reverseBetween(head, m, n): dummy = ListNode(0) dummy.next = head pre = dummy # 得到第 m - 1 个节点 for _ in range(m - 1): pre = pre.next cur = pre.next tail = cur.next # 反转从第 m 个节点到第 n 个节点的部分链表 for _ in range(n - m): cur.next = tail.next tail.next = pre.next pre.next = tail tail = cur.next return dummy.next ``` 该算的时间复杂度为 O(n - m),其中 n 是链表的长度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码骑士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值