“'神马’都是浮云,应聘技术岗位就是要踏实写程序。”
----田超(微软,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;
}
后面的方法只给了关键代码,如果需要完整的,只需要把相应的函数加入到第一个程序中,调用就可以了!