《剑指offer》:[1]反转一个单链表

     “'神马’都是浮云,应聘技术岗位就是要踏实写程序。”

                                                              ----田超(微软,SDE II)      

      模模糊糊也不是第一次看《剑指offer》这本书了,发现里面讲的还是比较基础,不能说讲的多么多么精湛高深,但是整本书确实有很多值得我们学习的技巧和方法,易错点,每次看都能学到新的东西,主要为了加深印象和锻炼一下编程动手能力。作为菜鸟程序猿一族这些书籍是绝对不能错过的,因为它是打开程序猿世界的一把钥匙,是万丈高楼的地基,是开战前的厉兵秣马,是我想登上山顶看风景必须经过的路。工欲善其事必先利其器,所以虽然这种写博客的方法速度比较慢,但是我还是相信一句话:“慢慢来,比较快”!急不能解决任何事,想一口吃个大胖子的理论是不成立的,曾经想“三个月征服一个国家“的日本也无异于痴人说梦,所以越是着急,时间越是紧迫,越需要我静下心来,脚踏实地,一步一步的向前走。如果一味的求快,反而会使效果更糟,忙中出错,用一颗浮躁的心怎么能学好东西做好事儿呢?以前也看过许多书,学过很多东西,但是记下来的又有多少呢?又掌握了多少呢?我觉得”一目十行“的阅读不适合技术人员,只是适合阅读小说传记。磨刀不误砍柴工,但是我相信每个人都有自己的学习方式,找到最适合自己的方法才是最重要的。只是我觉得这样的方法适合现在的自己,所以我会利用现在的时间坚持下去,拒绝走马观花,拒绝心浮气躁,拒绝眼高手低。 不啰嗦了,下面进入正题,希望能一天进步一点儿!慢慢的变得的强大起来!
       该博客学习笔可能不是按照《剑指offer》的目录顺序来的,所以可能有些乱!今天就从链表开始吧!以后会按顺序来的。乱就乱吧。。。
       链表是被提及的最频繁的数据结构。链表的结构很简单,它由指针把若干个结点连接成链状结构。参考《剑指ofer》,对链表的反转总结如下。
       链表的优点:插入删除效率高;动态分配内存,链表的长度不限;

       解决的问题:输入一个链表的头结点,从尾到头打印该链表。
        考虑这个题的时候,我们需要考虑到在打印的时候是否可以改变链表的结构:
       一、不改变链表的结构:

        方法一:借助数据结构栈来完成。因为第一个元素最后一个打印这就是栈的数据结构特性。(其实辅助数组也行,将链表中的数据保存在数组中,然后再利用下标逆序打印数组)。

具体实现代码如下:

#include<iostream>  
#include <algorithm>  
#include <stack>  
using namespace  std;  
typedef struct List
{
	int number;
	List *pNext;
}list;
list *pHead=NULL;
list *pEnd=NULL;
list *pNode=NULL;
void CreateList()
{
	int data;
	cout<<"please input the datas:"<<endl;
	cin>>data;
	while(0!=data)
	{
		pNode=new List;
		pNode->number=data;
		pNode->pNext=NULL;
		if(NULL==pHead)
		{
			pHead=pNode;
			pEnd=pNode;
		}
		else
		{
			pEnd->pNext=pNode;
			pEnd=pNode;
		}
		cin>>data;
	}
}
void showlist()
{
	list *pTemp=pHead;
	cout<<"List:";
	while(NULL!=pTemp)
	{
		cout<<pTemp->number<<" ";
		pTemp=pTemp->pNext;
	}
	cout<<endl;
}
void reverselist()
{
	stack<List *>node;
	list *pTemp=pHead;
	while(NULL!=pTemp)
	{
		node.push(pTemp);
		pTemp=pTemp->pNext;
	}
	cout<<"ReverseList:";
	while(!node.empty())
	{
		pTemp=node.top();
		cout<<pTemp->number<<" ";
		node.pop();
	}
	cout<<endl;
}
int main()
{
	CreateList();
	showlist();
	reverselist();
	system("pause");
	return 0;
}

数组的思想类似,代码也比较简单,所以就不写了!

运行结果:


方法二:递归的思想。

思想比较简单。代码如下:

void Recursion(List *pHead)
{
	List *pTemp=pHead;
	if(NULL!=pTemp)
	{
		if(NULL!=pTemp->pNext)
		{
			Recursion(pTemp->pNext);
		}
		cout<<pTemp->number<<" ";
	}
}
二、改变链表的结构:

方法一:借助三个指针。思想是:逐个的反转

具体代码如下:

List* three_pointers(List *pHead)
{
	List *pNode=pHead;
	List *prev=NULL;
	List *newhead=NULL;//这里的newhead可以省略,但是为了代码的可读性,增加了一个标记;
	while(NULL!=pNode)
	{
		List *next=pNode->pNext;
		if(NULL==next)
		{
			newhead=pNode;
		}
		pNode->pNext=prev;
		prev=pNode;
		pNode=next;
	}
	return newhead;
}
方法二:两个指针。 思想是:从第二个结点到第N个结点,依次逐结点插入到head结点之后,最后将头结点插入到尾部即可。

代码如下:

List* Two_pointers(List *pHead)
{
	List *q=NULL;
	List *p=pHead->pNext;
	while(NULL!=p->pNext)
	{//p一直指向第二个元素不变;
		q=p->pNext;
		p->pNext=q->pNext;
		q->pNext=pHead->pNext;
		pHead->pNext=q;
	}
	p->pNext=pHead; //形成环;
	pHead=p->pNext->pNext;
	p->pNext->pNext=NULL;//断环赋值尾NULL;
	return pHead;
}

后面的方法只给了关键代码,如果需要完整的,只需要把相应的函数加入到第一个程序中,调用就可以了!


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值