1.合并两个有序链表
归并思想是用来合并两个有序数组的思想,也可以用来合并两个有序链表:
1.创建一个新的链表,然后开始两个链表开始比较大小,小的放到新链表中,然后继续比较;
2.当一个链表为空时,那么将另一个链表中剩下的全部结点都放到新链表数据后面;
3.特殊情况就是两个链表至少有一个为空。这时返回另一个链表的头结点。
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
struct ListNode *newhead=NULL, *tail=NULL;
//当两个链表任意一个为空 或都为空
if(list1 == NULL)
{
return list2;
}
else if(list2 == NULL)
{
return list1;
}
//开始比较
while(list1 && list2)
{
if(list1->val < list2->val)
{
if(newhead == NULL)
{
newhead = tail = list1;
}
else
{
tail->next = list1;
tail = list1;
}
list1 = list1->next;
}
else
{
if(newhead == NULL)
{
newhead = tail = list2;
}
else
{
tail->next = list2;
tail = list2;
}
list2 = list2->next;
}
}
//多的放到后面
if(list1 == NULL)
{
tail->next = list2;
}
else
{
tail->next = list1;
}
return newhead;
}
接下来要介绍哨兵结点,哨兵结点就是指向单链表头部结点的一个结点,不在乎它内部存储的val。利用他可以省去判断newhead是否空的过程,会减少很多麻烦:
大体思路与普通方法相类似。不过在返回指针时要注意,newhead为stand哨兵结点,所以要返回newhead的next,要先创建一个next指针保存下来,释放掉stand,然后返回next。
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
struct ListNode *newhead, *tail;
struct ListNode* stand = (struct ListNode*)malloc(sizeof(struct ListNode));
stand->next = NULL;
newhead = tail = stand;
//当两个链表任意一个为空 或都为空
if(list1 == NULL)
{
return list2;
}
else if(list2 == NULL)
{
return list1;
}
//开始比较
while(list1 && list2)
{
if(list1->val < list2->val)
{
tail->next = list1;
tail = list1;
list1 = list1->next;
}
else
{
tail->next = list2;
tail = list2;
list2 = list2->next;
}
}
//多的放到后面
if(list1 == NULL)
{
tail->next = list2;
}
else
{
tail->next = list1;
}
struct ListNode *next = newhead->next;
free(newhead);
return next;
}
2.链表分割
分析:这道题应该先分割为两个链表,一个链表放比给定数字小的,另一个放大于或者等于的给定数字的结点。最后再将第一个链表放在第二个链表前面合成一个链表,在这里依然用两种方式做,一种是带哨兵结点的,一种是不带哨兵结点的。
特殊情况:
- 链表为NULL,直接返回NULL;
- 当给出的链表中的数据均小于或大于给定数据时,greaterhead或者lesshead为空,写代码时应注意这一点;
- 在实现代码时要防止成环问题,要及时将greatertail-》next置空。详情看下图:
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
ListNode *lesshead = NULL, *greaterhead = NULL;
ListNode *lesstail = lesshead, *greatertail = greaterhead;
ListNode* cur = pHead;
if(cur == NULL)
return NULL;
else
{
while(cur)
{
if(cur->val < x)
{
if(lesshead == NULL)
lesstail = lesshead = cur;
else
{
lesstail->next = cur;
lesstail = cur;
}
cur = cur->next;
}
else
{
if(greaterhead == NULL)
greatertail = greaterhead = cur;
else
{
greatertail->next = cur;
greatertail = cur;
}
cur = cur->next;
}
}
if(greaterhead != NULL)
greatertail->next = NULL;//防止死循环
if(lesshead != NULL)
lesstail->next = greaterhead;
}
if (lesshead != NULL)
return lesshead;
else
return greaterhead;
}
};
当我们引入哨兵结点时,就不会上面注意情况中的2情况了,但是同时也要注意,不要返回哨兵结点,也不要把哨兵结点放到最终的链表中去:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
ListNode* lesshead = (ListNode*)malloc(sizeof(ListNode));
ListNode* greaterhead = (ListNode*)malloc(sizeof(ListNode));
lesshead->next = NULL;
greaterhead->next = NULL;
ListNode *lesstail = lesshead, *greatertail = greaterhead;
ListNode* cur = pHead;
if(cur == NULL)
return NULL;
else
{
while(cur)
{
if(cur->val < x)
{
lesstail->next = cur;
lesstail = cur;
cur = cur->next;
}
else
{
greatertail->next = cur;
greatertail = cur;
cur = cur->next;
}
}
greatertail->next = NULL;//防止死循环
lesstail->next = greaterhead->next;
}
free(greaterhead);
ListNode* next = lesshead->next;
free(lesshead);
return next;
}
};