也是在做链表题目时,有一道题是用链表结构进行插入排序,因此,对插入排序的数组结构和链表结构做了一个总结,并分析了它们的复杂度。
插入排序:将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增加1的有序表。
1、顺序表的插入排序
关键:有两重循环,第一层循环是遍历所有无序元素,第二层循环是遍历已排好序的部分并进行插入
顺序表结构:
1 #define MAXSIZE 100 2 struct SqList 3 { 4 int data[MAXSIZE]; 5 int length; 6 };
插入排序代码:
1 oid insertsort(SqList *p) 2 { 3 int i,j; 4 //数组长度为length,但是遍历只进行length-1次 5 for (i = 0;i < p->length-1;i++) 6 { 7 if (p->data[i] > p->data[i+1]) 8 { 9 int temp = p->data[i+1]; 10 for (j = i;j>=0&&(p->data[j] > temp);j--) 11 { 12 p->data[j+1] = p->data[j]; 13 } 14 //for循环结束后j又减去1,所以data从j+1算起 15 p->data[j+1] = temp; 16 } 17 } 18 }
2、单链表结构的插入排序
关键:创建一个新链表,将待排序链表的每一个结点有序的插入到新链表中
链表结构:
1 struct SqList2 2 { 3 int data; 4 SqList2 *next; 5 SqList2(int x):data(x),next(NULL) {}; 6 };
插入排序代码:
1 //对不带有头结点的单链表进行插入排序 2 SqList2* insertsort2(SqList2 *p) 3 { 4 SqList2 *sortedHead = new SqList2(INT_MIN); 5 while(p != NULL) 6 { 7 //保存p的位置,p的位置一直在移动,直到将p中所有无序的元素都插入sortedHead有序序列中为止 8 SqList2 *temp = p->next; 9 SqList2 *cur = sortedHead; 10 //因为cur的头结点无用,所以直接从cur的第一个节点起插入,如果cur->next不为NULL并且cur->next->data比p->data小则移动cur位置,否则直接插入 11 while(cur->next != NULL && cur->next->data < p->data) 12 { 13 cur = cur->next; 14 } 15 //插入(当比cur->data小,比cur->next->data大时,将结点p插入cur与cur->next中间) 16 p->next = cur->next; 17 cur->next = p; 18 //前面对p做了改动,现在恢复p 19 p = temp; 20 } 21 return sortedHead->next; 22 }
链表插排代码补齐:
创建带有头结点的单链表:
1 //创建带有头结点的单链表 2 SqList2* createlinklist(SqList2 *s,int n) 3 { 4 SqList2 *p,*r; 5 int m; 6 int i; 7 s = (SqList2*)malloc(sizeof(SqList2)); 8 r = s; 9 for (i=0;i<n;i++) 10 { 11 p = (SqList2*)malloc(sizeof(SqList2)); 12 cin >> m; 13 p->data = m; 14 r->next = p; 15 r = p; 16 } 17 r->next = NULL; 18 return s; 19 }
主函数:
1 void main() 2 { 3 SqList2 *s = new SqList2(INT_MIN); 4 //创建带有头结点的单链表 5 s = createlinklist(s,5); 6 //向插入排序函数传入不带头结点的链表 7 s = insertsort2(s->next); 8 for (int i = 0;i<5;i++) 9 { 10 cout << s->data << " "; 11 s = s->next; 12 } 13 system("pause"); 14 }
结果:
3、复杂度分析:
顺序表插排复杂度:从空间上来看,它需要一个记录的辅助空间,所有空间复杂度为O(1)。从时间上来看,最好的情况是:排序表本身就是有序的,则只需要比较每一项,没有移动的记录,所以时间复杂度为O(n)。最坏的情况是,待排序表是逆序的,此时需要比较的次数和需要移动的次数都达到最大值,此时的时间复杂度是O(n2)。插排也是一直比较稳定的排序方法。
单链表插排复杂度:空间复杂度是O(1),时间复杂度是O(n2)。