对链表进行插入排序 试试这题
插入排序算法:
插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
整体思路:我们就按照插入排序的基本思想,先拿出一个结点当做头结点,然后后面每次都拿出一个结点跟前面的结点的val比较,如果val更大则进行尾插,若val较小,则进行中间插入或者头插,但是每种插入方式都有所不同,头插要注意head头指针的改变,中间插入要注意用三个指针配合使用,尾插要注意最后尾指针要指向NULL。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
typedef ListNode Node;
ListNode* insertionSortList(ListNode* head) {
if(head == NULL || head->next == NULL)
return head;
//取下第一个结点当做新链表的头结点
Node* newhead = head;
head = head->next;
newhead->next = NULL;//记得要置空
//1.将每个节点取下比对val大小
Node* cur = head;
while(cur)
{
Node* next = cur->next;
if(newhead->val >= cur->val)
{
//头插
cur->next = newhead;
newhead = cur;
}
else
{
//尾插或者中间插入
//用连个指针遍历链表,比较链表元素的大小
//如果>sortcur的val,sortcur就向后移动,如果<=sortcur的val(中间插入)或者NULL(尾插)就在sortcur前面插入该元素
Node* sortcur = newhead->next;
Node* sortprev = newhead;
if(sortcur == NULL)
{
sortprev->next = cur;
cur->next = NULL;
cur = next;
continue;
}
while(sortcur->val < cur->val)
{
if(sortcur->next == NULL)//尾插
{
sortcur->next = cur;
cur->next = NULL;
break;
}
sortcur = sortcur->next;
sortprev = sortprev->next;
}
//中间插入
if(sortcur->val >= cur->val )
{
sortprev->next = cur;
cur->next = sortcur;
}
}
cur = next;
}
return newhead;
}
};
这种方法是头插然后尾插最后中间插
还有一种:可以头插然后中间插最后尾插
新加的注释会用###标注
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode Node;
struct ListNode* insertionSortList(struct ListNode* head){
if(head == NULL || head->next == NULL)
return head;
//取下第一个结点当做新链表的头结点
Node* newhead = head;
Node* cur = head->next;//###从第二个结点取下来接在链表的后面
newhead->next = NULL;//记得要置空
//1.将每个节点取下比对val大小
while(cur)
{
Node* next = cur->next;//###/先保留next后面的指针
if(newhead->val >= cur->val)
{
//头插
cur->next = newhead;
newhead = cur;
}
else
{
//尾插或者中间插入
//用连个指针遍历链表,比较链表元素的大小
//如果>sortcur的val,sortcur就向后移动,
//如果<=sortcur的val(中间插入)或者NULL(尾插)就在sortcur前面插入该元素
Node* sortcur = newhead->next;
Node* sortprev = newhead;
//###让sortcur指针遍历链表一遍,一一比大小
while(sortcur)//###中间插入
{
if(cur->val <= sortcur->val)
{
sortprev->next = cur;
cur->next = sortcur;
break;
}
else
{
sortprev = sortcur;
sortcur = sortcur->next;
}
}
//###如果跳出来了,则就除了break掉的情况外,就是尾插的情况了,
//###这样就比上面一种方法少一次判断
//###尾插
if(sortcur == NULL)
{
sortprev->next = cur;
cur->next = NULL;
}
}
cur = next;//###循环迭代回去
}
return newhead;
}
其实第二种更符合清晰的思维逻辑,头插,中间插,尾插,一种一种情况的考虑