思路
对数组插入排序时,是两重循环,第一重是从第二个元素开始遍历整个数组,第二个就是反向循环,从当前元素开始向前寻找第一个小于当前数的值,并插到它后面。
但单链表无法反向,所以第二重循环就可以进行正向遍历,找到第一个大于当前结点值的结点,并插到它前面。
借助两个指针sort和unsort,分别指向待排序的第一个元素,和未排序的最后一个元素,且unsort->next==sort。
1,当前元素大于链表第一个元素就直接头插法
2,当前元素不大于第一个元素,就从第二个元素开始遍历已排序的元素(利用p和q两个指针),要么已排序都小于当前元素,则插入尾部。要么找到大于当前元素的节点,插在该节点前即可。
错误点
1,unsort与sort对比是从第二个元素开始遍历,L->next->next开始
2,遍历要遍历完sort中最后一个元素,因为之前只和第一个元素对比过了。
代码
#include<stdio.h>
#include "malloc.h"
#include<stdlib.h>
#include<time.h>
//定义链表结构体
typedef struct LinkList
{
int data;
int id;//唯一标识每个节点
struct LinkList* next;
}LinkList;
//交换链表中两个数据
void swap(LinkList* p, LinkList* min)
{
int temp = p->data;
p->data = min->data;
min->data = temp;
};
void Insertsort(LinkList* L)
{
LinkList* sort, * unsort, * p, * q;
if (L != NULL) { //保证链表不为空
sort = L->next;//指向排序好部分的最后一个元素
while (sort->next != NULL)//遍历未排序的第一个元素
{
unsort = sort->next;//每次循环都指向未排序的第一个元素
if (unsort->data < L->next->data) { //未排序的元素小于链表第一个元素
sort->next = unsort->next;//头插法,把第一个未排序的插入表头
unsort->next = L->next;
L->next = unsort;
}
else
{
q = L->next;
p = q->next;//从第二个元素开始遍历,第一个在上面头插法对比过了
while (unsort->data >= p->data) {//直到找到p>unsort
if (p->id == unsort->id)//遍历到unsort就停止,若遍历到unsort前一个就会少对比sort的最后一个元素
break;
q = p;
p = p->next;
}
if (p->id == unsort->id) {//遍历到unsort前。说明未排序元素均大于已排序元素,插入队尾
sort = unsort;
}
else//未遍历到unsort前,找到了大于未排序元素的p,插入p前
{
sort->next = unsort->next;
unsort->next = p;
q->next = unsort;
}
}
}
}
}
//输出链表节点
void print(LinkList* L)
{
LinkList* p = L;
for (int i = 0; i < L->data; ++i)//L为头结点不能动 否则每次遍历就会改变条件
{
printf("%d-%d ", p->next->id, p->next->data);
p = p->next;
}
}
void test()
{
//建立链表
LinkList* L = (LinkList*)malloc(sizeof(LinkList));
if (L == NULL) {
printf("内存分配不成功!\n");
}
else
{
L->data = 10;
LinkList* p = L;
srand(time(0));
for (int i = 0; i < L->data; ++i)
{
p->next = (LinkList*)malloc(sizeof(LinkList));
if (p->next) {
p = p->next;
p->data = rand() % 100;//取0-99的随机数 0-99,都为原值,100-199为0-99,以此类推
p->id = i;
}
}
p->next = NULL;
printf("原始序列为:\n");
print(L);
Insertsort(L);
printf("\n排序后为:\n");
print(L);
}
}
int main()
{
test();
}