目录
1.链表的定义,优劣势,基本实现看以往博客;
2.以下介绍关于链表的特殊操作:
1)单链表的反向输出:
实现思想:利用了递归的思想(或者说栈的后进先出的特点)
实现要点:怎么理解这里的递归,怎么用?递归的结束标志是什么?上代码:
void printReverse(Node* p) {
if (p == NULL) {
return;
}
printReverse(p->next);
printf("%d ", p->data);
}
这里递归的结束点就是return,向主调返回。具体怎么实现就是这样,通过先递归后输出就可以实现从后往前输出;
2)单链表的反转:
实现思想:找到前面的结点和后面的结点,让后面的结点连接前面的结点,确保后面的后面的结点不丢失,所以还需要一个结点记住;
实现要点:结点反转操作的步骤不能随意改变。上代码:
void reverse() {
if (head == NULL) {
printf("没有链表,还无法反转!");
return;
}
Node* pre = head;
Node* temp = head->next;
Node* tail = temp->next;
pre->next = NULL;
while (temp != NULL) {
tail = temp->next;
temp->next = pre;
pre = temp;
temp = tail;
//上面是让tail一直在temp的后面;
// 两个想法最后达到的效果一样,为什么下面会报错;
//我是想着,三个指针同时动,每次都移动一位;
/*temp->next = pre;
pre = temp;
temp = tail;
if (temp == NULL)
{
break;
}
tail = tail->next;*/
}
head = pre;
}
上面的注释部分就是一个错误演示:会导致空指针赋值的异常。
3)单链表的归并排序
实现思想:主要还是递归。通过每一层函数实现分区的操作,并对两个有序链表地分区进行合并,不断地把一个链表拆分为多个小分区。
实现要点:首先,准备一个函数用来合并两个有序链表。其次,准备中间值分区函数。最后定义排序函数,先上代码:
struct ListNode* findMid(struct ListNode* head);
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2);
struct ListNode* sortList(struct ListNode* head) {
if(head == NULL||head->next == NULL){
return head;
}
struct ListNode* middle = findMid(head);
struct ListNode* right = middle->next;
middle->next = NULL;
struct ListNode* left = sortList(head);
struct ListNode* sortedRight = sortList(right);
return mergeTwoLists(left,sortedRight);
}
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
//利用递归思想:
//每一层只需要返回一个链表就行了
//上一层只需要 next = 下一层的链表;
if(list1 == NULL){
return list2;
}
if(list2 == NULL){
return list1;
}
if(list1->val<=list2->val){
list1->next = mergeTwoLists(list1->next,list2);
return list1;
}
else{
list2->next = mergeTwoLists(list2->next,list1);
return list2;
}
}
struct ListNode* findMid(struct ListNode* head){
//找中间;
struct ListNode* k = head->next;
struct ListNode* m = head;
while(k && k->next){
m = m->next;
k = k->next->next;
}
return m;
}
来解释一下代码:
1.findMid函数就是找到链表中间值,通过快指针“一步两块”,慢指针“一步一块”,当快指针走到null或者,他的next走到null;那么慢指针处就是中间点。
2.mergeTwoLists函数作用:合并两个有序链表。如果只有单个链表返回就行。如果确实有两个有序链表合并,我们就用递归的思想(这里假设升序),如果list1的数据<=list2的数据,那么,就把list1的结点单独拿出来,再调用函数,参数为list1->next和list2,每一层返回一个链表,最后就输出了.
3.sort函数其实就是先分区,再合并,但是由于合并操作在最后,所以其实是把链表先分到实在不能再分,然后逐层合并返回.