插入排序

也是在做链表题目时,有一道题是用链表结构进行插入排序,因此,对插入排序的数组结构和链表结构做了一个总结,并分析了它们的复杂度。

插入排序:将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增加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)。

 

posted @ 2016-05-09 16:54  泥石流小盆友  阅读(225)  评论(0编辑  收藏  举报