- 对于近乎有序的数据而言插入排序算法十分高效。
- 对于规模很小的数据插入排序也是极佳的选择,由于其所进行的操作很简单所以平均每次操作的开销都很小。这一点使得像快速排序以及归并排序等算法都用插入排序来处理自己划分出来的小区间以优化性能
- 插入排序是稳定的排序算法,即不改变相同大小元素的原始次序关系。
链表类:
struct ListNode
{
int val;
ListNode *next;
ListNode (int x): val(x), next(NULL) {}
};
链表的插入排序实现原理很简单,就是一个元素一个元素的从原链表中取出来,然后按顺序插入到新链表中,时间复杂度为
,是一种效率并不是很高的算法,但是空间复杂度为,以高时间复杂度换取了低空间复杂度。代码如下:
ListNode *insertionSortList(ListNode *head)
{
ListNode *sortedHead = new ListNode(-1);
while (head != NULL)
{
// 利用一个临时变量来保存head的下一个节点,head节点为当前待插入的节点
ListNode *temp = head->next;
// sortedHead用于保存当前排序好的链表的开始节点
// 每次插入当前head节点时都需要从sortedHead节点开始
ListNode *inser = sortedHead;
// 寻找插入位置
while(inser->next != NULL && inser->next->val < head->val)
{
inser = inser->next;
}
// 插入到inser与inser下一个节点的之间
head->next = inser->next; //所以先将待插入节点head的下一个节点链入inser的下一个节点
inser->next = head; // inser的下一个节点更新为head节点,完成插入
head = temp; //将head节点处理完之后,更新head节点
}
return sortedHead->next;
}
每次用temp保留原始链表中的下一个待插入节点,用head来指示当前要插入的节点,插入过程如下图:
主函数:
int main()
{
ListNode n1(2), n2(1), n3(5), n4(3), n5(6);
n1.next = &n2;
n2.next = &n3;
n3.next = &n4;
n4.next = &n5;
ListNode *head = NULL;
head = insertionSortList(&n1);
ListNode *head1;
head1 = head;
while (head1 != NULL)
{
cout << head1->val << endl;
head1 = head1->next;
}
return 0;
}