在链表插入排序时,需要将一个链表拆分成两个链表,其中一个为有序链表,也就是只含头节点和一个数据节点,因为当只有一个数的时候就是有序的,另外一个链表含有剩下的数据节点,我们要实现的就是将这个含有剩下数据节点的链表一个节点一个节点的按从小到大的顺序插入到只有一个数据节点的链表里,从而实现链表从小到大的排序。
如上图,将一个链表拆分成两个链表,q指向含剩下数据节点的链表
接下来要做的就是将q指向的链表里面的第一个数据和含头节点的第一个数据比较,如果比他小,那么就插入到这个数据节点的前面,比他大就插入到这个数据节点的后面,然后将q指向第二个数据,又继续和已经排好序的两个数据进行比较,插入到合适的位置,一直到q所指向的地址为NULL为止。
如果q指向的第一个数据节点比含头节点链表里面的第一个数据节点小,我们就可以利用pre这个指针实现数据的插入,如果比他大,pre和prel就继续右移,继续比较,当比较到最后一个数据节点之后发现q指向的数据节点值最大,那么就通过pre指针插入到最后一个数据节点的后面。
综上,双指针的插入排序,prel指针负责访问指向的数据节点里面的数据和待插入的数据节点进行比较,pre指针负责节点插入时候的内存地址交换。
具体以核心代码进行讲解
插入排序的算法
node *q,*p, *pre,*prel; //定义指针q指向拆分的数据节点,定义指针pre,prel分别指向头含节点链表前后两个节点 q = head->next->next; //这两行实现链表的拆分 head->next->next = NULL; while (q!=NULL) //循环到q指向的地址为NULL为止 { p = q->next; //当一个数据节点插入成功后,需要q指向下一个数据节点,利用p指针实现 pre = head; // 指向头节点 prel = head->next; //指向第一个数据节点 while (prel != NULL) { if (prel->a > q->a) //如果待插入的数据比含头节点链表里的数据小 { q->next = pre->next; //就直接通过pre指针插入到数据前面 pre->next = q; break; //然后停止继续比较 } pre = pre->next; //两指针的右移 prel = prel->next; } if (pre->next==prel) //判断上面的循环是否执行完,如果执行完,说明待插入的数据比比较的大,那么就应该插入到数据节点的后面 { q->next = pre->next; pre->next = q; } q = p; //通过p实现q指向下一个数据,继续循环比较下一个数据,找出插入的位置 }
双指针实现的插入排序逻辑清晰,如果我说的地方很混乱,请大家自己看代码理解,我相信很容易就能理解