单链表表元链接顺序颠倒方法综述

什么是反转链表

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

即让第一个表元变成最后一个表元,第二个表元变成倒数第二个表元.....最后一个表元变成第一个表元

本文介绍三种方法,其他方法皆大同小异。

三种方法中:第一种方法采用在自身链表中进行操作,不引入其他任何链表。后两种方法采取引入一个工作链表,将反转后的链表放到工作链表里面。

先给出基本的结构:

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

struct intnode {
	int value;
	struct intnode *next;
} *q, *q1, *q2;

void show(struct intnode *p) {
	while (p) {
		printf("%d ", p->value);
		p = p->next;
	}
}

q,q1,q2用来取值,进而验证反转的正确性

法一:循环颠倒指向:

从第一个开始颠倒,直到最后一个,简单朴实,注意的是颠倒之后,指针指向完全颠倒,即head指向了原来的最后一个表元

struct intnode *reverse(struct intnode *head) {
	struct intnode *pre, *cur, *t;//t是辅助表元,pre是前驱,cur是后驱
	pre = NULL;
	cur = head;
	while (cur != NULL) {//关键就在这往下四行
		t = cur->next;//保护cur的后继指针,以免丢失
		cur->next = pre;//让cur指向pre
		pre = cur;//调整pre为cur
		cur = t;//cur指向下一个,进行下一次循环颠倒
	}
	return pre;
}

当然,为了完备性,上述应该再考虑head=NULL的情况,但上述并未进行考虑。其中,while循环中的四行代码是这个方法的关键。请读者细细品味。

在这里,我们把颠倒后的链表返回。所以构建了struct intnode * reverse函数,当然也可以用void,直接将反转后的链表输出,而不再返回。

void reverse(struct intnode *head) {//当然,法一不返回结构指针也可以,同理下述
	struct intnode *pre, *cur, *t;//t是辅助表元,pre是前驱,cur是后驱
	pre = NULL;
	cur = head;
	while (cur != NULL) {//关键就在这往下四行
		t = cur->next;//保护cur的后继指针,以免丢失
		cur->next = pre;//让cur指向pre
		pre = cur;//调整pre为cur
		cur = t;//cur指向下一个,进行下一次循环颠倒
	}
	show(pre);
}

法二:头插法插入到工作链表:

引入工作链表,通过头插法,把链表按顺序插入到工作链表中

struct intnode *reverse(struct intnode *head) {//头插法
	struct intnode *new_head = NULL, *temp = NULL;
	if (head == NULL || head->next == NULL)
		return head;
	while (head != NULL) {
		temp = head;			//将 temp 从 head 中摘除
		head = head->next;
		temp->next = new_head;	//将 temp 插入到 new_head 的头部
		new_head = temp;
	}
	return new_head;
}

在这里,关键的也是while之中的四行代码,把需要反转的链表,按顺序依次,头插法插入工作链表中,这样,新形成的工作链表就是反转好的链表。

法三:递归插入到工作链表:

引入工作链表,通过递归,实现反转。

struct intnode *reverse(struct intnode *head) {
	if (head == NULL || head->next == NULL)
		return head;
	else {
		struct intnode *new_head = reverse(head->next);//通过递归,从前往后依次颠倒
		head->next->next = head;
		head->next = NULL;
		return new_head;
	}
}

进而,主函数内随便给链表取值,验证下结果正确性

int main() {
	q  = (struct intnode *)malloc(sizeof(struct intnode));
	q1 = (struct intnode *)malloc(sizeof(struct intnode));
	q2 = (struct intnode *)malloc(sizeof(struct intnode));
	q->next = q1;
	q1->next = q2;
	q2->next = NULL;
	q->value = 1;
	q1->value = 2;
	q2->value = 3;//随便初始化几个值来验证最后结果
	show(q);
	printf("\n");
	q = reverse(q); 
	show(q);
	return 0;
}

完整代码

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

struct intnode {
	int value;
	struct intnode *next;
} *q, *q1, *q2;

void show(struct intnode *p) {
	while (p) {
		printf("%d ", p->value);
		p = p->next;
	}
}

/*法一:循环颠倒指向:从第一个开始颠倒,直到最后一个,简单朴实,注意的是
颠倒之后,指针指向完全颠倒,即head指向了原来的最后一个表元
另注:返回一个指针,函数要用指针类型的*    */
struct intnode *reverse(struct intnode *head) {
	struct intnode *pre, *cur, *t;//t是辅助表元,pre是前驱,cur是后驱
	pre = NULL;
	cur = head;
	while (cur != NULL) {//关键就在这往下四行
		t = cur->next;//保护cur的后继指针,以免丢失
		cur->next = pre;//让cur指向pre
		pre = cur;//调整pre为cur
		cur = t;//cur指向下一个,进行下一次循环颠倒
	}
	return pre;
}

void reverse(struct intnode *head) {//当然,法一不返回结构指针也可以,同理下述
	struct intnode *pre, *cur, *t;//t是辅助表元,pre是前驱,cur是后驱
	pre = NULL;
	cur = head;
	while (cur != NULL) {//关键就在这往下四行
		t = cur->next;//保护cur的后继指针,以免丢失
		cur->next = pre;//让cur指向pre
		pre = cur;//调整pre为cur
		cur = t;//cur指向下一个,进行下一次循环颠倒
	}
	show(pre);
//	head=pre;
}

/*法二:递归:通过递归,把反转后的链表放到新的链表里面*/
struct intnode *reverse(struct intnode *head) {
	if (head == NULL || head->next == NULL)
		return head;
	else {
		struct intnode *new_head = reverse(head->next);//通过递归,从前往后依次颠倒
		head->next->next = head;
		head->next = NULL;
		return new_head;
	}
}

/*法三,同法二,但不递归:通过头插法,把反转后的链表放到新的链表里面*/
struct intnode *reverse(struct intnode *head) {//头插法
	struct intnode *new_head = NULL, *temp = NULL;
	if (head == NULL || head->next == NULL)
		return head;
	while (head != NULL) {
		temp = head;			//将 temp 从 head 中摘除
		head = head->next;
		temp->next = new_head;	//将 temp 插入到 new_head 的头部
		new_head = temp;
	}
	return new_head;
}

int main() {
	q  = (struct intnode *)malloc(sizeof(struct intnode));
	q1 = (struct intnode *)malloc(sizeof(struct intnode));
	q2 = (struct intnode *)malloc(sizeof(struct intnode));
	q->next = q1;
	q1->next = q2;
	q2->next = NULL;
	q->value = 1;
	q1->value = 2;
	q2->value = 3;//随便初始化几个值来验证最后结果

	show(q);
	printf("\n");

	reverse(q);  
	show(q);

	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

可曾听闻忆灵

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

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

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

打赏作者

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

抵扣说明:

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

余额充值