• 插入排序


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

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

  • 相关阅读:
    数据库同步软件介绍以及使用说明(SyncNavigator多元异构数据实时同步工具)
    关于异构数据库的不同表之间数据同步的操作细节---syncnavigator同步工具实操
    ASP.NET Core 配置文件(无处不在的依赖注入)
    ASP.NET Core 开源项目整理
    性能差异 ASP.NET WebForm与ASP.NET MVC
    MySQL 分区知识点(三)
    Docker 资料
    MySQL 基础知识(基本架构、存储引擎差异)
    MySQL InnoDB与MyISAM存储引擎差异
    MySQL 索引知识整理(创建高性能的索引)
  • 原文地址:https://www.cnblogs.com/tracyhan/p/5474340.html
Copyright © 2020-2023  润新知