C语言 单链表的反转

C语言 单链表的反转

一、简述

       记--简单的将单链表的数据顺序进行反转。如将原来的顺序1 2 3 4 5 6 7  反转为:7 6 5 4 3 2 1

二、方式1:头插法

        2.1 头插法1--类似新建链表

        2.1.1 思路:断开链表头,然后以头插法的方式将原链表的数据添加链表。

              

        2.1.2 测试代码

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

//链表节点定义 
typedef struct s_node
{
	int data;
	struct s_node* pNext;
}Node;

Node* create_list_head();
Node* create_new_node(int node_data);
int add_node_head(Node* head, Node* new_node);
void display_list(Node* head);
void free_list(Node* head);
Node* revert_list(Node* head);
 
int main(int argc, char *argv[])
{
	//创建链表 
	Node* head = create_list_head();
	if(NULL == head)
	{
		printf("create_list_head failed!\n");
		return -1;
	}
	
	//填充数据(添加节点) 
	int i;
	for(i=1; i<8; i++)
		add_node_head(head, create_new_node(i));

	//打印原来链表数据 
	printf("befor "); 
	display_list(head);
	
	//反转链表
	head = revert_list(head); 
	printf("after "); 
	display_list(head);
	
	//释放链表空间 
	free_list(head);
	return 0;
}

//创建链表 
Node* create_list_head()
{
	Node* head = (Node*)malloc(sizeof(Node));
	if(NULL != head)
	{
		head->data= -1;
		head->pNext= NULL;	
	}
	return head;
} 

//创建新节点 
Node* create_new_node(int node_data)
{
	Node* new_node = (Node*)malloc(sizeof(Node));
	if(NULL != new_node)
	{
		new_node->data= node_data;
		new_node->pNext= NULL;	
	}	
	return new_node;
}

//头插法
int add_node_head(Node* head, Node* new_node)
{
	if(NULL == head || NULL == new_node)
		return -1;
 	new_node->pNext = head->pNext;
	head->pNext = new_node;
	return 0; 
} 

//打印链表数据 
void display_list(Node* head)
{
	if(NULL == head)
		return;
	Node* tmp = head;
	printf("list data:");
	while(NULL !=(tmp=tmp->pNext))
	{
		printf("%d  ", tmp->data);
	}
	printf("\n");
}

//释放链表 
void free_list(Node* head)
{
	if(NULL == head) 
		return;
	Node* p = head;
	while(p = p->pNext)
	{
		head->pNext = p->pNext;
		//printf("free:%d\n", p->data);
		free(p);
		p = head;
	}
	free(head);
} 

//头插方式1-反转链表 
Node* revert_list(Node* head)
{
	if(NULL == head)
		return;

	Node* p = head->pNext;
	head->pNext= NULL;
	Node* tmp = NULL;
	while(p)
	{
		tmp = p->pNext;
		add_node_head(head, p); 
		p = tmp;	
	}
	
	return head;
} 

        2.1.3 测试结果

              

        2.2 头插法2 --与方式1雷同

         2.2.1 思路:除了第一个逐个往插入到最前面

         2.2.2 测试代码

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

//链表节点定义 
typedef struct s_node
{
	int data;
	struct s_node* pNext;
}Node;

Node* create_list_head();
Node* create_new_node(int node_data);
int add_node_head(Node* head, Node* new_node);
void display_list(Node* head);
void free_list(Node* head);
Node* revert_list(Node* head);
 
int main(int argc, char *argv[])
{
	//创建链表 
	Node* head = create_list_head();
	if(NULL == head)
	{
		printf("create_list_head failed!\n");
		return -1;
	}
	
	//填充数据(添加节点) 
	int i;
	for(i=1; i<8; i++)
		add_node_head(head, create_new_node(i));

	//打印原来链表数据 
	printf("befor "); 
	display_list(head);
	
	//反转链表
	head = revert_list(head); 
	printf("after "); 
	display_list(head);
	
	//释放链表空间 
	free_list(head);
	return 0;
}

//创建链表 
Node* create_list_head()
{
	Node* head = (Node*)malloc(sizeof(Node));
	if(NULL != head)
	{
		head->data= -1;
		head->pNext= NULL;	
	}
	return head;
} 

//创建新节点 
Node* create_new_node(int node_data)
{
	Node* new_node = (Node*)malloc(sizeof(Node));
	if(NULL != new_node)
	{
		new_node->data= node_data;
		new_node->pNext= NULL;	
	}	
	return new_node;
}

//头插法
int add_node_head(Node* head, Node* new_node)
{
	if(NULL == head || NULL == new_node)
		return -1;
 	new_node->pNext = head->pNext;
	head->pNext = new_node;
	return 0; 
} 

//打印链表数据 
void display_list(Node* head)
{
	if(NULL == head)
		return;
	Node* tmp = head;
	printf("list data:");
	while(NULL !=(tmp=tmp->pNext))
	{
		printf("%d  ", tmp->data);
	}
	printf("\n");
}

//释放链表 
void free_list(Node* head)
{
	if(NULL == head) 
		return;
	Node* p = head;
	while(p = p->pNext)
	{
		head->pNext = p->pNext;
		//printf("free:%d\n", p->data);
		free(p);
		p = head;
	}
	free(head);
} 

//新建链表方式-反转链表 
Node* revert_list(Node* head)
{
	if(NULL == head)
		return;
	
	Node* p = head->pNext;
	Node* q = NULL;
	while(q = p->pNext)
	{
		p->pNext = q->pNext;//分离q 
		add_node_head(head, q);//将q插入到首元素位置 
	}
	
	return head;
} 

         2.2.3 测试结果

     

 三、方式2 尾插方式

        3.1 思路:找到最后一个元素,然后从第一个元素逐个插入到尾部。

        3.2 测试代码

#include <stdio.h>
#include <stdlib.h>
 
//链表节点定义 
typedef struct s_node
{
	int data;
	struct s_node* pNext;
}Node;
 
Node* create_list_head();
Node* create_new_node(int node_data);
int add_node_tail(Node* head, Node* new_node); 
void display_list(Node* head);
void free_list(Node* head);
Node* revert_list(Node* head);
 
int main(int argc, char *argv[])
{
	//创建链表 
	Node* head = create_list_head();
	if(NULL == head)
	{
		printf("create_list_head failed!\n");
		return -1;
	}
	
	//填充数据(添加节点) 
	int i;
	for(i=1; i<8; i++)
		add_node_tail(head, create_new_node(i));
 
	//打印原来链表数据 
	printf("befor "); 
	display_list(head);
	
	//反转链表
	head = revert_list(head); 
	printf("after "); 
	display_list(head);
	
	//释放链表空间 
	free_list(head);
	return 0;
}
 
//创建链表 
Node* create_list_head()
{
	Node* head = (Node*)malloc(sizeof(Node));
	if(NULL != head)
	{
		head->data= -1;
		head->pNext= NULL;	
	}
	return head;
} 
 
//创建新节点 
Node* create_new_node(int node_data)
{
	Node* new_node = (Node*)malloc(sizeof(Node));
	if(NULL != new_node)
	{
		new_node->data= node_data;
		new_node->pNext= NULL;	
	}	
	return new_node;
}
 
//尾插法 
int add_node_tail(Node* tail, Node* new_node)
{
	if(NULL == tail || NULL == new_node)
		return -1;	
	new_node->pNext = tail->pNext; //新节点指向原来的tail->pNext
	tail->pNext = new_node;//新节点成为tail->pNext 
	return 0;
} 
 
//打印链表数据 
void display_list(Node* head)
{
	if(NULL == head)
		return;
	Node* tmp = head;
	printf("list data:");
	while(NULL !=(tmp=tmp->pNext))
	{
		printf("%d  ", tmp->data);
	}
	printf("\n");
}
 
//释放链表 
void free_list(Node* head)
{
	if(NULL == head) 
		return;
	Node* p = head;
	while(p = p->pNext)
	{
		head->pNext = p->pNext;
		//printf("free:%d\n", p->data);
		free(p);
		p = head;
	}
	free(head);
} 
 
//尾插方式-反转链表 
Node* revert_list(Node* head)
{
	if(NULL == head)
		return;
	
	Node *p = head->pNext, *end = head;
	while( NULL != end->pNext )//使得end指向链表最后一个元素
	{
		end = end->pNext;
	}
	 
	while(p != end)
	{
		head->pNext = p->pNext;//分离p
		add_node_tail(end, p);//将p插入到末尾位置
		p = head->pNext;//p指向第一个元素 
	}
	
	return head;
}

        3.3 测试结果

四、方法3 递归反转 

 1、递归结束边界:节点为NULL, 或当前节点指向NULL

 2、状态转移方程:反转(1到N) = 先反转(1到N-1),再将N添加到尾部

测试代码:(注意,本例子与上面的例子稍有差异,为了方便表述,头节点也作为使用并存储数据了)

#include <stdio.h>
#include <stdlib.h>
 
#define NODE_COUNT	3
 
//链表节点定义 
typedef struct s_node
{
	int data;
	struct s_node* pNext;
}Node;
 
Node* create_list_head();
Node* create_new_node(int node_data);
int add_node_tail(Node* head, Node* new_node); 
void display_list(Node* head);
void free_list(Node* head);
Node* revert_list(Node* head);
 
int main(int argc, char *argv[])
{
	//创建链表 
	Node* head = create_list_head();
	if(NULL == head)
	{
		printf("create_list_head failed!\n");
		return -1;
	}
	
	//填充数据(添加节点) 
	int i;
	for(i=1; i < NODE_COUNT; i++)
		add_node_tail(head, create_new_node(i));
 
	//打印原来链表数据 
	printf("befor "); 
	display_list(head);
	
	//反转链表
	head = revert_list(head); 
	printf("after "); 
	display_list(head);
	
	//释放链表空间 
	free_list(head);
	
	getchar();
	return 0;
}
 
 
//创建新节点 
Node* create_new_node(int node_data)
{
	Node* new_node = (Node*)malloc(sizeof(Node));
	if(NULL != new_node)
	{
		new_node->data= node_data;
		new_node->pNext= NULL;	
	}	
	return new_node;
}
 
//创建链表 
Node* create_list_head()
{
	return create_new_node(NODE_COUNT); 
}
 
//尾插法 
int add_node_tail(Node* tail, Node* new_node)
{
	if(NULL == tail || NULL == new_node)
		return -1;	
	new_node->pNext = tail->pNext; //新节点指向原来的tail->pNext
	tail->pNext = new_node;//新节点成为tail->pNext 
	return 0;
} 
 
//打印链表数据 
void display_list(Node* head)
{
	if(NULL == head)
		return;
	Node* tmp = head;
	printf("list data:");
	while(NULL != tmp)
	{
		printf("%d  ", tmp->data);
		tmp = tmp->pNext;
	}
	printf("\n");
}
 
//释放链表 
void free_list(Node* head)
{
	if(NULL == head) 
		return;
	Node* p = head;
	while (p) {
		head = head->pNext;
		printf("free:%d\n", p->data);
		free(p);
		p = head;
	}
} 
 
//反转链表 
Node* revert_list(Node* head)
{
	if (NULL == head || NULL == head->pNext) {
		return head;
	}
	
	Node* new_head = revert_list(head->pNext);
	
	head->pNext->pNext = head;
	head->pNext = NULL;
	
	return new_head;
}

 测试结果:

好的,下面是单链表反转C语言实现代码: ```c #include<stdio.h> #include<stdlib.h> struct ListNode { int val; struct ListNode *next; }; struct ListNode* reverseList(struct ListNode* head) { struct ListNode* prev = NULL; struct ListNode* curr = head; while (curr != NULL) { struct ListNode* nextTemp = curr->next; curr->next = prev; prev = curr; curr = nextTemp; } return prev; } int main() { struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode)); head->val = 1; head->next = (struct ListNode*)malloc(sizeof(struct ListNode)); head->next->val = 2; head->next->next = (struct ListNode*)malloc(sizeof(struct ListNode)); head->next->next->val = 3; head->next->next->next = NULL; struct ListNode* new_head = reverseList(head); while (new_head != NULL) { printf("%d ", new_head->val); new_head = new_head->next; } return 0; } ``` 这段代码中,我们首先定义了一个 `ListNode` 结构体,表示单链表的节点。其中,`val` 表示节点的值,`next` 表示指向下一个节点的指针。接着,我们定义了 `reverseList` 函数,用于反转单链表。在函数中,我们使用了三个指针变量 `prev`、`curr` 和 `nextTemp`,分别表示当前节点的前一个节点、当前节点和当前节点的后一个节点。在循环中,我们不断地将当前节点的 `next` 指针指向前一个节点,然后更新三个指针变量的值,直到当前节点为 `NULL`。最后,我们返回反转后的单链表的头指针 `prev`。在 `main` 函数中,我们构造一个简单的单链表,并且调用 `reverseList` 函数进行反转,最后输出反转后的单链表的节点值。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值