8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
链表倒置
干货之前的一点废话
自己下意识的觉得数据结构对编程来说应该是基础而且重要的东西。毕竟关于各种语言的特性,只能在大量的使用中渐渐领悟,而关于数据结构,关于算法却是在各种语言中通用的。
在人生中第一次求职面试中,面试官问了我一个简单而基础的问题——单链表的倒置。这个问题简单考察了关于链表的知识,当时的我没答上来,后来解决了这个问题之后,我对C语言的指针与引用也有了更清晰的认识。
指针与引用
在讲链表倒置之前先提一点关于C的东西,那就是&与*,前者表示引用,而后者表示指针。
所谓指针,实际上就是保存地址的一种变量。而引用,就是取变量的存储地址。例如:1
2
3
4
5
6
7
8int *p=(int *)malloc(sizeof(int));
int *p=NULL;
int a=0;
int *p=a;
//因为指针所指的是内存地址,所以在给指针赋初值时,只能用已得到内存的变量,或是采用malloc动态分配内存。如果暂时不确定指针的指向,应将它初始化为NULL。
int a=0;
int * p=a;
//这里声明了一个整型指针变量p,p表示存储一个整型变量的地址,而*p则表示p地址里存储的整型变量。
我们可以从下面这段代码体会一下:1
2
3
4
5
6
7#include
void main(){
int a=2;
int *b=&a; //这行代码也可以变成这样:int *b=NULL; b=&a;就是说int *b=&a; 中的*只是为了声明b是一个指针,在程序的其它地方*b表示一个整型变量,是不能用一个地址给它赋值的。
if(&a==b)
printf("&a = b");
}
最后再来总结一下,p是一个指针变量。
那么&p就表示存储p变量的地址,p表示&p这个地址中存储的值,也是一个地址,通俗的讲就是指针p所指变量的地址,而*p则表示指针p所指的变量。也就是p所指的地址中保存的值
C语言实现单链表
要实现链表的倒置,我们应该先明确链表是什么。
这里为什么要明确头结点和尾节点的概念呢,只有知道头结点和尾节点在哪,你才能找到自己分配给每一个结点的内存,在不需要它的时候,才能准确地把它释放掉。
链表的名字已经告诉了我们它是像铁链一样一环扣一环的东西。而它的每一环是这样的:1
2
3
4typedef struct LNode{
int data;
struct LNode * next;
}LinkNode;
这里有一点递归的思想,一个结构体中保存了两个变量,data保存的是这个节点的信息,在这个实例中它是整型的,而next则是与这个结构体相同类型的指针变量,它指向“下一节铁链”。
在我们对链表有了一个概念之后,我们将试着造出一节节铁链并把它连起来。1
2
3
4
5
6
7
8
9
10
11
12
13void CreatList(int a[],LinkNode *L,int n){
int i=0;
LinkNode *s1=L,*s2=NULL;
for(i=0;i
printf("%dn",i);
s2=(LinkNode *)malloc(sizeof(LinkNode)); //这里使用了动态分配内存的方法。
s2->data=a[i];
s1->next=s2;
s1=s2;
}
s1->next=NULL;
}
我们可以写一个函数来直观地感受一下链表。1
2
3
4
5
6
7
8
9void Traverse(LinkNode *L){
int i=0;
LinkNode *s3=L;
while(s3!=NULL){
i++;
printf("第%d节铁链为%dn",i,s3->data);
s3=s3->next;
}
}
链表倒置
非递归方式1
2
3
4
5
6
7
8
9
10
11
12void Reverse1(LinkNode **L){ //这里直接把L指针的地址作为参数传进去了,函数能够改变L指针的值。
LinkNode *next=NULL,*prev=NULL;
while(*L!=NULL){
next=(*L)->next;
(*L)->next=prev;
prev=*L;
*L=next;
}
*L=prev;
Traverse(*L);
}1
2
3
4
5
6
7
8
9
10
11LinkNode * Reverse2(LinkNode *L){//这里实参的值不会发生改变,所以需要返回头结点
LinkNode *next=NULL,*prev=NULL;
while(L!=NULL){
next=L->next;
L->next=prev;
prev=L;
L=next;
}
return prev;
}
递归方式1
2
3
4
5
6
7
8LinkNode * Reverse3(LinkNode *L){//头结点需要提前保存。
LinkNode *s=NULL;
if(L->next==NULL)
return L;
s=Reverse3(L->next);
s->next=L;
L->next=NULL;
}