目录
———————————————— 天气之子·幻 ————————————————
1、移除元素
思路:
创建一个新链表(newhead,newtail),遍历原链表,把不等于 val 的结点尾插到新链表中。
/**
* definition for singly-linked list.
* struct listnode {
* int val;
* struct listnode *next;
* };
*/
typedef struct listnode listnode;
struct listnode* removeelements(struct listnode* head, int val) {
//创建新链表
listnode* newhead;listnode* newtail;
newhead=newtail=null;
//遍历数组
listnode* pcur=head;
while(pcur)
{
if(pcur->val!=val)
{
//又分两种情况,链表为空,不为空
if(newhead==null)
{
newtail=newhead=pcur;
}
else
{
newtail->next=pcur;
newtail=newtail->next;
}
}
pcur=pcur->next;
}
//[7,7,7,7,7],val=7 ,这种情况下,newtail=null,newtail->next=null,此时newtail不能解引用,所以加上if条件
if(newtail)
newtail->next=null;
return newhead;
}
注意:
当原链表为空时,newhead = newtail = pcur;
在实例中,最后一个5结点被尾插到新链表中时,5结点的next指针指向的仍然是后面的6结点,所以最后返回的时候结果里面含有6,所以我们把最后一个等于val结点的next指针指向null即可!
2、反转链表
新奇思路:
/**
* definition for singly-linked list.
* struct listnode {
* int val;
* struct listnode *next;
* };
*/
typedef struct listnode listnode;
struct listnode* reverselist(struct listnode* head) {
//链表也有可能是空链表
if(head==null)
{
return head;
}
//定义三个指针变量
listnode* n1,*n2,*n3;
n1=null;n2=head;n3=n2->next;
while(n2)
{
n2->next=n1;
n1=n2;
n2=n3;
if(n3)
n3=n3->next;
}
return n1;
}
3、链表的中间节点
思路:
奇数个结点
偶数个结点
/**
* definition for singly-linked list.
* struct listnode {
* int val;
* struct listnode *next;
* };
*/
typedef struct listnode listnode;
struct listnode* middlenode(struct listnode* head) {
listnode* slow=head;
listnode* fast=head;
//while(fast->next&&fast)错误,不可互换顺序,当为偶数个结点时,fast==null循环结束,但是while
循环内会先判断fast->next,空指针不能解引用,会报错
while(fast&&fast->next)
{
//慢指针每次走一步
//快指针每次走两步
slow=slow->next;
fast=fast->next->next;
}
//此时slow指向的结点恰好是中间结点
return slow;
}
快慢指针为什么可以找到中间结点?(快慢指针的原理)
慢指针每次走一步,快指针每次走两步,当快指针走到链表的尾结点时,假设链表的长度为n,快指针走的路程是慢指针的两倍,2*慢=快,即慢指针走的路程是n/2。
4、合并两个有序链表
思路:
创建一个新链表,newhead,newtail 指向新链表的头结点,定义两个指针分别指向原链表的头结点,两个指针指向的数据比较大小,谁小谁尾插到新链表里面。思路清晰,不过要注意很多细节,直接上代码:
/**
* definition for singly-linked list.
* struct listnode {
* int val;
* struct listnode *next;
* };
*/
typedef struct listnode listnode;
struct listnode* mergetwolists(struct listnode* list1, struct listnode* list2) {
//处理原链表为空链表的情况
if(list1==null)
{
return list2;
}
if(list2==null)
{
return list1;
}
//创建一个新链表
listnode* newhead=null;
listnode* newtail=null;
//创建两个指针分别指向两个链表的头结点来遍历原链表
listnode* l1=list1;
listnode* l2=list2;
while(l1&&l2)
{
if(l1->val<l2->val)
{
//l1尾插到新链表
if(newtail==null)
{
newtail=newhead=l1;
}
else
{
newtail->next=l1;
newtail=newtail->next;
}
l1=l1->next;
}
else
{
//l2尾插到新链表
if(newhead==null)
{
newtail=newhead=l2;
}
else
{
newtail->next=l2;
newtail=newtail->next;
}
l2=l2->next;
}
}
//出循环,要么l1==null,要么l2==null
if(l1)
newtail->next=l1; 想想这里为啥不用while循环?
if(l2)
newtail->next=l2;
return newhead;
}
//优化过后,申请一个不为空的链表,就无需再判断新链表是否为空,最后不要忘记free
/**
* definition for singly-linked list.
* struct listnode {
* int val;
* struct listnode *next;
* };
*/
typedef struct listnode listnode;
struct listnode* mergetwolists(struct listnode* list1, struct listnode* list2) {
//链表为空的情况
if(list1==null)
{
return list2;
}
if(list2==null)
{
return list1;
}
//创建一个新链表
listnode* newhead,*newtail;
newhead=newtail=(listnode*)malloc(sizeof(listnode));
//定义两个指针来遍历数组
listnode* l1=list1;
listnode* l2=list2;
while(l1&&l2)
{
if(l1->val<l2->val)
{
newtail->next=l1;
l1=l1->next;
newtail=newtail->next;
}
else
{
newtail->next=l2;
l2=l2->next;
newtail=newtail->next;
}
}
if(l1)
newtail->next=l1;
if(l2)
newtail->next=l2;
listnode* ret=newhead->next;
free(newhead);
newhead=null;
return ret;
}
完—
relaxing time!!!
———————————————— 天气之子·幻 ————————————————
至此结束——
再见——
发表评论