两种链表反转的方法(头插法和原地反转法,图解清晰,一看就会)

我写博客是为了把我自己学到的东西在加深一下印象,希望大家多多指出错误,万分感谢

为了下面方便写子函数,我先把主函数放在前面

#include<stdio.h>
#include<stdlib.h> 
struct Node* creatlist(struct Node* head,int n);
struct Node*filplist(struct Node* head);
typedef struct Node{
	int num;
	struct Node *next;
}node;
int main()	
{
	node *head=(node*)malloc(sizeof(node));
	head->next=NULL;
	int n;
	printf("输入n:");
	scanf("%d",&n);
	head=creatlist(head,n);
	head=filplist(head);
	return 0; 
}

node* creatlist(node* head,int n)
{
	node *tail,*p;
	tail=head;
	printf("输入%d个数:",n);
	for(int i=0;i<n;i++)
	{
		p=(node*)malloc(sizeof(node));
		scanf("%d",&p->num);
		tail->next=p;
		tail=p; 
	} 
	tail->next=NULL;// 特别重要 
	return head;
}

一.原地反转法

大家先看一下下面这张图
在这里插入图片描述
一开始的初始状态就是第一行的状态,p指针始终在1号结构体上,而q指针指向的结构体就要移到前面去。
第一步就是先让p连上q后面的那个结构体,防止丢失,所以对应的代码为
p=q->next;
第二部就是让q连上p,在让head连上q,所以对应的代码为
q->next=head->next;
head->next=q;
第三步就是再让q到p的前面去,
q=p->next;
后面就依次循环就可以了
而循环的条件是什么呢
看上面的图就可以发现,当程序结束时,q指针指向的是NULL,
所以,我们可以用q !=NULL作为循环结束的条件
接下来我以子函数的形式来写这个程序

struct Node*filplist(struct Node* head)
{
	node *p,*q;
	p=head->next;
	q=head->next->next;
	while(q!=NULL)
	{
		p=q->next;
		q->next=head->next;
		head->next=q;
		q=p->next;
	}
	return head;
}

以上就是原地反转链表的代码了

二 .头插法反转链表

我写的链表基础这篇博客上说到过用头插法来创建链表是得到的结果是与我们输入的结果相反的,所以我们可以利用头插法来反转链表
话不多说,先看图

在这里插入图片描述

看到初始状态,p指向1号结构体,而head的指向的是NULL,这就是初始状态
接下来,通过图不难看出p指向的结构体就是要接到head后面的结构体
第一步就是要先把p指向的下一个结构体用指针q保存下来,所对应的代码为:
q=p->next;
第二步要把p所指向的结构体接到head后面,所对应的代码为:
p-next=head->next;
head->next=p;
第三步就是让p跑到q所在的位置,所对应的代码为:
p=q;
后面就是通过循环来解决了,同样是用while循环来实现,可以看到上图,循环结束的时候p指针是指向NULL的,所以循环终止的条件为p!=NULL。
接下来我以子函数的形式来写这个程序

struct Node*filplist(struct Node* head)
{
	node *p,*q;
	p=head->next;
	head->next=NULL;
	while(p!=NULL)
	{
		q=p->next;
		p->next=head->next;
		head->next=p;
		p=q;
	}
	return head;
}

以上就是头插法反转链表的代码了

注意:创建链表时最后的一个结构体一定要指向NULL,否则在后续的运行中会出现码指针越界的情况(我踩过的坑)
本人还在刚刚开始学数据结构,对递归和迭代还不清楚,所以只会这两种笨的方法了

以上就是两种关于反转链表的方法了,欢迎大家多多指出错误和提供更好的解决方案。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
头插法是一种反转链表方法,它通过将原链表的每个节点插入到新链表的头部,从而实现链表反转。下面是使用头插法反转链表C语言代码: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构体 struct ListNode { int val; struct ListNode* next; }; // 头插法反转链表 struct ListNode* reverseList(struct ListNode* head) { struct ListNode* newHead = NULL; // 新链表的头节点 while (head != NULL) { struct ListNode* nextNode = head->next; // 保存下一个节点的指针 head->next = newHead; // 将当前节点插入到新链表的头部 newHead = head; // 更新新链表的头节点 head = nextNode; // 移动到下一个节点 } return newHead; } // 创建链表 struct ListNode* createList(int* nums, int size) { struct ListNode* head = NULL; struct ListNode* tail = NULL; for (int i = 0; i < size; i++) { struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode)); newNode->val = nums[i]; newNode->next = NULL; if (head == NULL) { head = newNode; tail = newNode; } else { tail->next = newNode; tail = newNode; } } return head; } // 打印链表 void printList(struct ListNode* head) { while (head != NULL) { printf("%d ", head->val); head = head->next; } printf("\n"); } int main() { int nums[] = {1, 2, 3, 4, 5}; int size = sizeof(nums) / sizeof(nums[0]); struct ListNode* head = createList(nums, size); printf("原链表:"); printList(head); struct ListNode* newHead = reverseList(head); printf("反转后的链表:"); printList(newHead); return 0; } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值