单链表操作之反转单链表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bitboss/article/details/51610992

***单链表操作之反转单链表***



//反转单链表,只能遍历一遍链表

// 定义的结点结构体和头指针结构体:

typedef int DataType;

typedef struct LinkNode
{
	DataType data;
	struct LinkNode* next;
}LinkNode,*pLinkNode;//结点结构体

typedef struct LinkList
{
	LinkNode* pHead;//头结点指针
}LinkList ,*pLinkList;//链表


// 函数原型:void ReserveList(pLinkList pList);

// 思路分析:

/*  看到反转链表,是否立马想到了反转字符串,回想一下,反转字符串时,一个指针找到尾部,然后一个指针指向头部,开始交换;但是要找到链表的尾部,就已经遍历了一遍链表;我用头尾指针没有反转成功链表,大家可以试试,指点一下我;

假设单链表现在是: 1----->2----->3----->4----->5
目标链表是:       5----->4----->3----->2----->1

目标链表更像是在源链表的基础上让头指针指向了 5,而5->4,4->3……;

照着这个思路的话,如果你直接让头指针指向5的话,是不是没法继续,因为其它节点的指针没办法获得,换个方法,我们一个一个结点指过去,最后让头指针指向5,试试看,定义一个cur指针,初始化为头指针,先让它指向 1;


第一步:先把 1的next用临时指针tmp保存起来,再定义个叫 newHead 的节点指针(注意:不是另外创建一个链表的头指针);然后让newHead(其实可以理解为目标链表的头指针)指向1;因为目标链表的 1 是最后一个元素,所以是不是应该将cur->next置为NULL;我们在这里再定一个指针ptr,初始化为NULL;让cur->next = ptr,同样达到了目的,然后ptr = cur,这个操作的目的放在第二步说,然后让cur指向2,也就是把tmp赋给cur,让循环动起来;

第二步:现在目标链表已经完成第一步,newHead指向了1,第二步就是让newHead指向2,并且2要指向1,第一步的时候我们用tmp保存了指向2的指针;最后用cur保存了tmp,那现在就可以先把指向3的指针保存起来,即 tmp = cur->next,接着做剩下的事,让newHead指向2,并且2要指向1,先让newHead = cur;接着让2指向1,实现起来的时候必定得先把指向1的指针保存起来,才能让2指向1,这就体现了我们ptr的妙处了,ptr每次都保存指向前一个节点的指针,下次循环直接让cur->next = ptr即可,在这里cur指向的是2;ptr和tmp呼应,tmp每次都是保存指向下一个结点的指针;

以此类推
,当newNode指向最后一个结点的时候结束循环,并且将newHead 赋给 头指针,这一步很重要,很多人都会忘记!因为我们改变的是源链表,而不是重建一个新的链表!

// 递归的方法后面学会后会补充!

*/
算法实现

void ReserveList(pLinkList pList)
{
	pLinkNode  NewHead  = NULL;
	pLinkNode ptr = NULL;
	pLinkNode cur = NULL;
	pLinkNode tmp = 0;

	assert(pList);
	
	cur = pList ->pHead ;//从头开始;

	while(cur)
	{
		tmp = cur->next ;//保存指向下一个结点的指针;
		NewHead = cur;//指向下一个节点
		cur->next = ptr;//让当前结点指向它源链表中的上一个结点;
		ptr = cur;//保存当前结点,在下一次循环中,就是指向上一个节点的指针;
		cur = tmp;//控制循环;
	}
	pList->pHead  = NewHead; //最后赋给头指针;
}


没有更多推荐了,返回首页