总是会想,等进入一个相对稳定的公司(环境)后,我再努力,再搞数据结构和算法、再搞懂公司的框架、再学好shell和python,时间总是充裕的。殊不知秉承着这样的思想,只是吃不起苦而找借口的一种变体罢了。
生活总会以平等的方式来回报你。只要涉及当场手写代码的面试便碰壁,目前为止顺利的只有创业型小公司和外包而已。这想必也反映了我现在的水平吧。我祈求自己以后能将每一天物尽其用,走出自我易满足而选择easy模式,给自己一种“貌似很努力”的而自我感动的泥沼。
再说到面试,链表反转如此基础的题目已经考到第二次了。我以前最害怕写算法,现在看来不写是不行了;根据“面试宝典”来实现一下吧:
首先以一个以0结尾的数组的作为参数,生成单链表。遍历数组直到遇0停止,该链表末元素的next指针为NULL。
#include <stdio.h>
#include <stdlib.h>
typedef struct _node{
int num;
_node* next;
}node;
node* createlink(int arr[])
{
int* tmp=arr;
node* head=(node*)malloc(sizeof(node));
head->num=0;
node* cur=head;
node* nxt;
while(*tmp!=0)
{
nxt=(node*)malloc(sizeof(node));
nxt->num=*tmp;
cur->next=nxt;
tmp++;
cur=nxt;
}
cur->next=NULL;
return head;
}
void printlink(node* head)
{
node* cur=head->next;
while(cur!=NULL){
printf("%d ",cur->num);
cur=cur->next;
}
printf("\n");
}
接着便是反转了。首先使用一个指针遍历链表是必需的。然而使用的这个指针却有讲究。
1). 将遍历指针定义为cur,即指向当前元素,cur=head。
如果cur->next=cur即1指向0后,然后cur移到1的位置。进行下次遍历时,由于是单向链表,1和2之间的关系已经被掐断,无法将2指向1。因此,遍历指针定义为cur是不可行的。
2). 将遍历指针定义为nxt,即指向当前元素的下一个元素,cur=head,nxt=cur->head。
考虑到刚才1)仅用到一个cur,由于next关系已经改变,无法访问到下一元素;而现在用到cur和nxt两个,在再次进入循环时,即便cur和nxt的next关系已经被掐断,依然可以让nxt->next=cur即2指向1。当然在nxt指针反转前,要先保存nxt->next供下次循环使用:
然后反转:
最后重置cur和nxt:
2->1的步骤和0->1的原理一样。另外考虑到本链表有头指针,因此指针反转前要判断cur是否是head。如是,则nxt->next=NULL。
当遍历到链表尾时nxt为NULL,则退出循环,将head指向cur。至此完成单链表反转。
代码:
node* reverse(node *head)
{
if(head==NULL)
return NULL;
node *tmp,*cur,*nxt;
cur=head;
nxt=cur->next;
while(nxt!=NULL){
tmp=nxt->next;
if(cur==head)
nxt->next=NULL;
else
nxt->next=cur;
cur=nxt;
nxt=tmp;
}
head->next=cur;
return head;
}
验证:
int main(int argc,char* argv[],char* envp[])
{
int arry[]={1,2,3,4,5,6,7,0};
node* nodhead=createlink(arry);
printlink(nodhead);
reverse(nodhead);
printlink(nodhead);
return 0;
}
结果: