使用插入排序对链表进行排序。
ListNode *insertionSortList(ListNode *head) { if (!head) return head; ListNode tmp(0); ListNode* p, *q, *t; while (head) { p = &tmp; q = p->next; t = head; head = head->next; while (q && q->val < t->val) { p = p->next; q = q->next; } t->next = q; p->next = t; } return tmp.next; }
//对这里面很多人表示无语,人家说插入排序, //我看排行榜里面很多人直接push节点到一个list, //sort一下,然后重新组织下链表。这些答案有何意义? //请管理员对这些答案进行清除。
//这题不是让用插入排序吗。。。评论里怎么各式各样的。。
//解释下:
// 插入排序就是不断的向一个已经排序的列表中(此处为代码中的sortedList)添加新的节点,并且保证添加节点后的列表仍然有序。
// 一开始的时候sortedList为空,需要遍历输入链表(也就是未排序链表,此处为形参head)的每一个节点,每遍历一个,sortedList加一个。
// cur代表的就是你当前要加入sortedlist的节点。cur要插入的位置在sortedList的哪里呢?就是此处代码中node的后面。 经过这么一轮,一个节点就被加入到了sortlist。之后同理。 /**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *insertionSortList(ListNode *head) {
if(head==nullptr || head->next==nullptr) return head;
//在插入时,有可能需要在链表头插入,为了方便,新建立个链表
ListNode sortedList(0);
ListNode *cur=head;
while(cur){
//因为cur的指向可能会改变,所以要预先存下cur的next,以备在下次循环时使用
ListNode *next=cur->next;
//node代表排序数组的当前节点
//从前向后遍历排序数组的每一个节点,和当前未排序数组中的节点做比较
ListNode* node=&sortedList;
while(node->next!=nullptr && node->next->val<cur->val) //以为第一个元素是0,所以从next开始
{
node=node->next;
}
cur->next=node->next;
node->next=cur;
cur=next;
}
return sortedList.next;
}
};
// 1. 添加了个伪链表头,简化设计 // 2. 利用递归 class Solution { public: ListNode *insertionSortList(ListNode *head) { if(!head || !head->next) return head; ListNode dummyHead(0), *p; dummyHead.next = insertionSortList(head->next); p = &dummyHead; while(p && p->next && head->val > p->next->val){ p = p->next; } head->next = p->next; p->next = head; return dummyHead.next; } };
public class Solution { public ListNode insertionSortList(ListNode head) { if(head==null||head.next==null) return head; ListNode cursors = head; ListNode tempCur = null; ListNode temp = head;//待排序元素的上一元素 ListNode current = temp.next;//待排序的元素 while(current!=null){ if(current.val<head.val){ //排序的元素比头小 把当前元素当做头 temp.next = current.next; current.next = head; head = current; }else{ // cursors-↓ ↓-temp // 1 -> 3 -> 5 -> 8 -> 4-> 12 -> 2 //tempCur-↑ current-↑ //插入后: // |-------有序---------| // 1 -> 3 -> 4 -> 5 -> 8-> 12 -> 2 //找到插入的位置 current插入到cursors的前面:temp->current->cursors tempCur = cursors; cursors = tempCur.next; while(cursors!=current&&cursors.val<current.val){ tempCur = cursors; cursors = cursors.next; } if(cursors==current){ temp = current; current = temp.next; }else{ temp.next = current.next; tempCur.next = current; current.next = cursors; } } cursors = head; current = temp.next; } return head; } }
/*思路:1.判断head和head->next是否为NULL 2.将head作为有序链表,将head->next作为待插入的链表,所以讲head和head->next分开(head->next=NULL) 3.比较大小的三种情况:(1)与头结点比较 (2)考虑pA=pA->next的情况 (3)其他 */ /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *insertionSortList(ListNode *head) { if (head == NULL || head->next == NULL) { return head; } ListNode* pB = head->next; head->next = NULL; ListNode *pA, *temp; while (pB != NULL) { pA = head; if (pB->val < head->val) { temp = pB->next; //pB->next = head; pB->next = pA; head = pB; pB = temp; } else { while (pA->next != NULL && pA->next->val < pB->val) { pA = pA->next; } temp = pB->next; pB->next = pA->next; pA->next = pB; pB = temp; } } return head; } };
Sort a linked list using insertion sort.
解题思路就是根据插入排序的思想,每次遍历都保证前n个数都是排好序的,那么按照原生的插入排序,是从当前元素前一个元素开始一个一个往前判断,只要比前面元素小,则往前移动,一直移动到有一个元素小于它或者移动到头部了则停止,这个位置就是当前元素在这一趟中应该在的位置。但是链表中不好往前移,只能每次都从头部开始往后判断,一直找到第一个比当前元素大的元素停止,然后调整一下指针,就是让当前元素插入到本趟合适的位置。由于有可能要与第一个元素交换,所以搞一个虚拟头节点处理起来会简单一点。
class Solution {
public ListNode insertionSortList(ListNode head) {
//1.判断一下
if(head == null || head.next == null){
return head;
}
//2.新建一个虚拟节点,后面要用
ListNode dummy = new ListNode(0);
//3.curr指向的节点及其后面所有节点都是未排序的,前面的都是排好序的
ListNode curr = head;
while(curr != null){
//4.每次循环,pre都重新指向dummy,dummy后一个节点到curr前一个节点都是排好序的
ListNode pre = dummy;
//5.保存一下当前节点后面一个节点的引用
ListNode next = curr.next;
//6.每次都从dummy节点下一个开始找,前面都是排好序的,如果小于当前节点则指针后移,一直找到pre.next为空
//或者比当前节点大的时候,停止,表明pre的下一个节点就是当前节点应该放的位置
while(pre.next != null && pre.next.val < curr.val){
pre = pre.next;
}
//7.找到当前节点应该放的位置之后,下面的工作就是移动指针,让curr插到pre和pre.next中间
//然后让curr后移一位,前面都是排好序的
curr.next = pre.next;
pre.next = curr;
curr = next;
}
//8.dummy后面就是我们所需要的用插入排序排好序的链表
return dummy.next;
}
}
class Solution { public: ListNode* insertionSortList(ListNode* head) { ListNode dummy(INT_MIN); ListNode *tail = &dummy, *curr = head; while (curr) { if (tail->val <= curr->val) { tail = tail->next = curr; curr = curr->next; } else { tail->next = curr->next; ListNode* p = &dummy; while (p->next->val < curr->val) p = p->next; curr->next = p->next; p->next = curr; curr = tail->next; } } return dummy.next; } };
import java.util.*; public class Solution { public static ListNode insertionSortList(ListNode head) { ListNode L=head; ListNode SL=head; if(head==null||head.next==null) return head; else{ int i=0; ArrayList al=new ArrayList(); while(head!=null){ al.add(head.val); head=head.next; } int[] a= new int[al.size()]; for(i=0;i<al.size();i++) { a[i]=(int) al.get(i); } getInsertSort(a);//和上一题一样,只不过换了一个排序算法,主方法里面几乎没变。 for(i=0;i<a.length;i++) { L.val=a[i]; L=L.next; } } return SL; } public static void getInsertSort(int[] a) { int n = a.length;//将数组的长度赋给n是为了防止每次for循环中判断时都调用length方法影响性能 int temp;//放于for循环外面是为了防止重复创建变量 int j; for(int i = 1; i < n;i++){//排序的趟数 temp = a[i];//赋给temp是为了防止索引i之前的元素向后移动覆盖了索引i的元素 j = i-1; for(; j>=0&&a[j]>temp; --j) {//将大于i位置元素的元素向后移 a[j+1] = a[j]; } a[j+1]= temp;//找到i应该在的位置,将值放置此处 } } }
public class Solution { public ListNode insertionSortList(ListNode head) { if(head == null || head.next == null) return head; ListNode r = head.next; head.next = null; while (r != null) { ListNode q = head; ListNode p = null; while (q != null && q.val < r.val) { p = q; q = q.next; } ListNode t = r.next; if(q == head) { r.next = head; head = r; } else { p.next = r; r.next = q; } r = t; } return head; } }
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *insertionSortList(ListNode *head) { if(head==NULL) return head; ListNode* p=head->next; ListNode* q=head; ListNode* r=head; //s=head; while(p!=NULL){ if(p->val>=q->val){ p=p->next; q=q->next; } else if(p->val<head->val){ q->next=p->next; p->next=head; head=p; //p,q update p=q->next; } else{ r=head; while(r->next->val<p->val){ r=r->next; } q->next=p->next; p->next=r->next; r->next=p; p=q->next; } } return head; } };
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *insertionSortList(ListNode *head) { ListNode *dummyHead = new ListNode(-1); ListNode *p1 = dummyHead, *p2 = head, *prev; while (p2 != nullptr) { while (p1 -> next != nullptr) { prev = p1; p1 = p1 -> next; if (p1 -> val > p2 -> val) { ListNode* rest = p2 -> next; prev -> next = p2; p2 -> next = p1; p2 = rest; p1 = dummyHead; break; } } if (p1 -> next == nullptr) { ListNode* rest = p2 -> next; p1 -> next = p2; p2 -> next = nullptr; p2 = rest; p1 = dummyHead; } } return dummyHead -> next; } };
public class Solution { public ListNode insertionSortList(ListNode head) { ListNode emptyNode = new ListNode(Integer.MIN_VALUE); while(head != null){ ListNode outNextNode = head.next, innerNode = emptyNode; while(innerNode.next != null && head.val > innerNode.next.val){ innerNode = innerNode.next; } head.next = innerNode.next; innerNode.next = head; head = outNextNode; } return emptyNode.next; } }
// 我觉得题目的本意是要求使用在原数组上进行插入排序,而不是新建链表、保存变量到容器排序后在写到原链表; //我的思路是:选中当前的结点 对比前面的所有结点(插入排序默认前面的结点都是排好序的) //如果都大于前面的结点则保持原地不动 //如果从头排序好的结点,如果出现小于本身的结点,则从链表上摘下自身节点并插入到比自己小的结点前面 //另外方便头结点的数据操作,增加了头指针辅助变量 class Solution { public: ListNode *insertionSortList(ListNode *head) { if (head == NULL) return NULL; //建立辅助头指针 ListNode * root = (ListNode *)malloc(sizeof(ListNode)); root->next = head;ListNode * current = head->next; //被比较的结点 ListNode * pre_current = head; //当前结点的前一个结点 while (current != NULL) { ListNode * temp = root->next; //类似迭代器 ListNode * pre_temp = root; //指向前一个指针 while (temp->val <= current->val && temp != current) { temp = temp->next; pre_temp = pre_temp->next; } if (temp != current) { //删除当前节点 deleteSortList(pre_current, current); //添加到合适的结点 insertSortList(pre_temp, current); current = pre_current->next; } else { //更改循环变量 current = current->next; pre_current = pre_current->next; } } head = root->next; free(root); return head; } private: ListNode *deleteSortList(ListNode *pre_ptr,ListNode *cur_ptr) { ListNode * del_ptr = cur_ptr; pre_ptr->next = del_ptr->next; return del_ptr; } void insertSortList(ListNode *pre_ptr,ListNode *add_ptr) { add_ptr->next = pre_ptr->next; pre_ptr->next = add_ptr; } };
Solution 1 /* 下面是效仿数组的插入排序的一种方法。 */ class Solution { public: ListNode *insertionSortList(ListNode *head) { if(head==nullptr||head->next==nullptr) return head; ListNode *p,*q; p=head->next; while(p!=nullptr)//从第二个元素开始插入 { q=p->next; p->next=nullptr;//将插入元素后指针置nullptr InsertList(head,p,q); p=q; } return head; } private: void InsertList(ListNode *&front,ListNode *obj,ListNode *_next) { ListNode *NewNode=new ListNode(obj->val); ListNode *q,*p; p=front; q=front->next; while(!(q->val==obj->val&&q->next==nullptr))//将待插指针从链表尾中删除 { p=p->next; q=q->next; } p->next=nullptr; q=front; if(q->val>obj->val)//当链表第一个元素大于待插元素时 { NewNode->next=front; front=NewNode; while(q->next!=nullptr) q=q->next; q->next=_next;//将差值完成的链表与后链表接起来 } else{ ListNode *temp; while(q!=nullptr) { if(q->val<obj->val)//寻找插入位置 { temp=q; q=q->next; } else break; } if(q!=nullptr)//插入位置在链表中间某个位置 { temp->next=NewNode; NewNode->next=q; while(q->next!=nullptr) q=q->next; q->next=_next; } else{ //插入位置在链表尾部 temp->next=NewNode; NewNode->next=_next; } } return ; } }; Solution 2 class Solution { public: ListNode *insertionSortList(ListNode *head) { if(head==nullptr||head->next==nullptr) return head; ListNode *NewList=new ListNode(0); ListNode *q,*p,*pre; while(head!=nullptr) { pre=NewList; q=pre->next; p=head; head=head->next; while(q!=nullptr&&q->val<p->val) { pre=pre->next; q=q->next; } pre->next=p; p->next=q; } return NewList->next; } };
public class Solution {
public ListNode insertionSortList(ListNode head) {
ListNode dummy = new ListNode(0);
while(head != null){
ListNode node = dummy;
while(node.next != null && node.next.val < head.val){
node = node.next;
}
ListNode tmp = head.next; //保存head的下一个节点
head.next = node.next; //拼接排序后半部分数组
node.next = head; //把前半部分排序数组和后半部分凭借
head = tmp; // 恢复head的下一个节点
}
return dummy.next;
}
}
//感觉自己写的太麻烦 我怎么感觉加了一个伪表头,反而麻烦了 public ListNode insertionSortList(ListNode head){ if(head==null||head.next==null) return head; ListNode first =new ListNode(-1); ListNode curIndex,last,slow,fast; first.next=head; last=head; curIndex=head.next; last.next=null; while(curIndex!=null){ //大于头节点 if(curIndex.val<=head.val){ first.next=curIndex; curIndex=curIndex.next; first.next.next=head; //last=head; head=first.next; } else if(curIndex.val>last.val){ last.next=curIndex; last=last.next; curIndex=curIndex.next; last.next=null; } else{ slow=head; fast=head.next; while(fast.val<curIndex.val){ slow=fast; fast=fast.next; } slow.next=curIndex; curIndex=curIndex.next; slow=slow.next; slow.next=fast; } } return first.next; }
class Solution { public: ListNode *insertionSortList(ListNode *head) { if(head==NULL || head->next==NULL) return head; ListNode L(0),*p; L.next = insertionSortList(head->next); p = &L; while(p && p->next && p->next->val < head->val) p = p->next; head->next = p->next; p->next = head; return L.next; } };