算法题:反转单链表

说明:本文仅供学习交流,转载请标明出处,欢迎转载!

题目:存在一个单链表,头指针为head,实现单链表的反转Node *Reverse(Node *head)。 

该算法的求解办法有很多,如:

方法1:先顺序变量单链表,将结点保存到栈中,在从栈中弹出结点,重新建立一个新的单链表;

方法2:用《剑指offer》里面给出的算法,用三个指针来实现;

方法3:采用递归实现,是方法2的递归实现形式。

本文主要给出方法2和方法3,在给出具体的代码之前,先要注意几个问题

         (1)如果head为空,该如何处理?

         (2)如果链表为单节点链表,该如何处理?

         (3)如何防止在反转过程中断链?

         (4)反转后head是否更新?

         (5)反转后得到的链表最后一个结点是否为null?

考虑完以上问题后,就可以写出正确的代码了。

代码实现如下:

<pre name="code" class="cpp">#include<iostream>
using namespace std;
struct Node
{
	int value;
	Node* next;
	Node(int v):value(v){}
};
/*创建一个链表,1->2->3->4->5->6->7*/
Node* CreateList()//创建一个单链表
{
   Node *head;
   Node *n1=new Node(1);
   Node *n2=new Node(2);
   Node *n3=new Node(3);
   Node *n4=new Node(4);
   Node *n5=new Node(5);
   Node *n6=new Node(6);
   Node *n7=new Node(7);
   head=n1;
   n1->next=n2;
   n2->next=n3;
   n3->next=n4;
   n4->next=n5;
   n5->next=n6;
   n6->next=n7;
   n7->next=NULL;
   return head;
}
void FreeList(Node *head)//将链表空间释放
{
	if(head==NULL)
	{
		return ;
	}
	else
	{
		Node *temp=head->next;
		delete head;
		head=temp;
		FreeList(head);
	}
}
void VisitList(Node *head)//遍历链表中的元素,用递归的方法遍历
{
	if(head)
	{
		cout<<head->value<<"->";
		VisitList(head->next);
	}
	else
	{
		cout<<"null"<<endl;
	}
}
Node *Reverse(Node *head)//反转单链表
{
	if(!head || !head->next)//如果是空链表或者仅含一个结点的链表
	{
		return head;
	}
	Node *p1,*p2,*temp;
	p1=head;
	p2=head->next;
	p1->next=NULL;//这是反正后链表的最后一个结点(即原来的第一个结点)
	while(p2)
	{
		temp=p2->next;//防止段链
		p2->next=p1;//反转
		//前进
		p1=p2;
		p2=temp;
	}
	head=p1;
	return p1;
}
Node *Reverse1(Node *head)//用递归法实现
{
	if(!head || !head->next)
	{
		return head;
	}
	Node *nextNode=head->next;
	head->next=NULL;
	Node *head1=Reverse(nextNode);
	nextNode->next=head;
	return head1;//这里是递归过程
}
int main()
{
	Node *head=CreateList();
	cout<<"原链表输出为:";
	VisitList(head);
	head=Reverse(head);
	cout<<"反转后的链表为(循环法):";//循环法
	VisitList(head);
	cout<<"再反转链表(递归法):";
	head=Reverse1(head);//递归法
	VisitList(head);
	FreeList(head);//释放链表空间
	return 0;
}

测试结果如下:

  参考资料-------------《剑指offer》

算法题:反转单链表

时间: 2024-10-12 06:47:04

算法题:反转单链表的相关文章

常见算法题:单链表二路归并

题目:现有两个递增的单链表L1和L2,设计一个算法将L1与L2的所有结点归并到递增的单链表L3中.要求:空间复杂度为O(1). 思路:本题可采用二路归并思路,但题目要求空间复杂度为O(1),因此不能复制结点,只能破坏L1和L2将结点插入到L3中. 代码: void Merge(LinkList &L1,LinkList &L2,LinkList &L3) { LinkList *p=L1.head->next, *q=L2.head->next; LinkList *p

C++算法之 反转单链表

题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点,链表节点定义为: struct ListNode { int    m_nValue; ListNode* m_pNext; }; 算法思路: 链表  1-->2-->3-->4-->5 建立一个 pPrev节点,而且为空节点:  pPrev = NULL:再建立一个节点pNode = pHead; 再建立第三个节点pNext = pNode->m_pNext; pNext的作用:用来保存pNode

【LeetCode-面试算法经典-Java实现】【092-Reverse Linked List II(反转单链表II)】

[092-Reverse Linked List II(反转单链表II)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Reverse a linked list from position m to n. Do it in-place and in one-pass. For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->

009实现一个算法来删除单链表中的一个结点,只给出指向那个结点的指针(keep it up)

呵呵,这个题不能直接删除已知的结点,因为是单链表,不知道前驱,只知道 后继结点,直接删除会使链表断开.不过我们可以删除已知结点的后继结点, 把后继结点的值赋值给已知结点. #include <iostream> struct Node { int data; Node* next; }; bool removeNode(Node* vNode) { if (vNode == NULL || vNode->next == NULL) return false; Node* pNext =

算法题:求链表倒数第K个结点

说明:本文仅供学习交流,转载请标明出处,欢迎转载!  题目:给出一个单链表,返回倒数第K个结点,最后一个结点为倒数第1个. <剑指offer>上面给的解法是设置两个指针,这里记为p1.p2,先让p2走(k-1)步,然后p1.p2同时走,当p2走到最后一个结点时,p1所指向的结点就是倒数第k个结点. 我觉得按照这样的逻辑写代码反而更容易出错,因为我们需要把我两件重要的问题:(1).p2先走(k-1)步:(2)循环结束的条件是p2到达最后一个结点,即p2->next==NULL.显然这样不太

递归、非递归 反转单链表

定义链表结构 struct ListNode { int val; ListNode *next; ListNode(int v) : val(v), next(NULL) {} }; 非递归反转单链表 ListNode* reverse(ListNode *root) { if (root == NULL || root->next == NULL) return root; ListNode *cur = root->next; root->next = NULL; while (c

C语言:【单链表】逆置反转单链表

#include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int DataType; typedef struct SListNode {     DataType data;     struct SListNode* next; }SListNode; SListNode* BuyNode(DataType x) {     SListNode* next = (SListNode*)malloc

实现一个算法从一个单链表中返回倒数第n个元素(keep it up)

我们维护两个指针, 它们之间的距离为n.然后,我将这两个指针同步地在这个单链表上移动,保持它们的距离 为n不变.那么, 当第二个指针指到空时,第一个指针即为所求. #include <iostream> struct Node { int data; Node* next; }; void initList(Node* vNode) { for (int i=0; i < 20; ++i) { Node* TempNode = new Node; TempNode->data =

cc150:实现一个算法来删除单链表中间的一个结点,只给出指向那个结点的指针

实现一个算法来删除单链表中间的一个结点,只给出指向那个结点的指针. 例子: 输入:指向链表a->b->c->d->e中结点c的指针 结果:不需要返回什么,得到一个新链表:a->b->d->e 解答 这个问题的关键是你只有一个指向要删除结点的指针,如果直接删除它,这条链表就断了. 但你又没办法得到该结点之前结点的指针,是的,它连头结点也不提供.在这种情况下, 你只能另觅他径.重新审视一下这个问题,我们只能获得从c结点开始后的指针, 如果让你删除c结点后的某个结点,那