链表的插入法排序
直接插入排序的基本思想:假设链表的前面n-1个节点是已经有值的 并且排好序的,
对于节点n在 这个序列中找插入位置,使得n插入后新序列仍然有序。
按照这种思想,依次对链表从头到尾执行一遍,就可以使无序链表变为有序链表。
head---->[1]------>[3]------> [2]...------>[n]------>[NULL](原链表head为空)
head ---->[1]---->[NULL](从原链表中取第1个节点作为只有一个节点的有序链表)
先在原链表中以第一个节点为一个有序链表,原链表剩下的视为无序链表。
请结合代码中的注释仔细分析。
插入法排序,不同于冒泡排序,选择排序需要将链表比较很多遍。
相反他只需要将链表遍历一遍就可以将排序完成。
直接插入排序的基本思想:假设链表的前面n-1个节点是已经有值的 并且排好序的,
对于节点n在 这个序列中找插入位置,使得n插入后新序列仍然有序。
按照这种思想,依次对链表从头到尾执行一遍,就可以使无序链表变为有序链表。
下面看单向链表的直接插入排序图示:
head---->[1]------>[3]------> [2]...------>[n]------>[NULL](原链表head为空)
head ---->[1]---->[NULL](从原链表中取第1个节点作为只有一个节点的有序链表)
first---->[3]---->[2]...---->[n]---->[NULL](first指向原链表剩下用于直接插入排序的节点)
先在原链表中以第一个节点为一个有序链表,原链表剩下的视为无序链表。
虽然是将一条链表截成两段,但实际上还是一条链表。
void sort(struct Sum *head) //传入链表头
{
struct Sum *p,*q,*t,*first; //定义中间指针变量。
head=head->next; //头节点为空则跳过头节点
first=head->next; //将剩余的链表默认为无序链表 head一直是有序链表的头结点
head->next=NULL; //提取出第一个节点为有序链表
while(first!=NULL) //当无序链表不为空
{
for(t = first,p = head;p !=NUL L&& p->num< = t->num;q = p,p = p->next); //跳出循环找出插入的点
first = first->next;//无序链表向后
if(p == head) //第一个节点不符合条件
head = t; //head中第一个节点 p->num 大于 无序链表 第一个节点 t->num,退出循环,
//应将 t节点放在第一个结点,所以令head = t
else
q->next = t; // q指向了p的上一个结点,将 t结点插入到 q结点之后。如果p == NULL, 则 t结点放在有序链表的末尾
t->next = p; //当 p != NULL 时 使 t插入到 p 前一个的位置。 当 p == NULL 时使t->next = NULL
//first = first->next; //虽然放在这里与性也没错,如果理解了上面加粗的那句话,会发现放在这里是不行的。
}
}
请结合代码中的注释仔细分析。