数据结构与算法--排序

一、排序的基本概念

          1) 排序: 将一组杂乱无章的数据按一定规律顺次排列起来

                 // 将无序序列排成一个有序序列(由小到大或由大到小)的运算

          2) 如果参加排序的数据结点包含多个数据域,那么排序往往是针对其中某个域而言

          3) 排序方法的分类:

        * 按数据存储介质:    内部排序和外部排序

                 // 内部排序:  数据量不大、数据在内存,无需内外存交换数据

                //  外部排序:  数据量较大、数据在外存(文件排序)

        * 按比较器个数:        串行排序和并行排序

                 // 串行排序:  单处理机(同一时刻比较一对元素)

                //  并行排序:  多处理机(同一时刻比较多对元素)

        * 按主要操作:           比较排序和基数排序

                 // 比较排序:  用比较的方法(插入排序、交换排序、选择排序、归并排序)

                //  基数排序:  不比较元素的大小,仅仅根据元素本身的取值确定其有序位置

        * 按辅助空间:           原地排序和非原地排序

                 // 原地排序:  辅助空间用量为O(1)的排序方法(所占的辅助存储空间与参加排序的数据量大小无关)

                //  原地排序:  辅助空间用量超过O(1)的排序方法

        * 按稳定性:               稳定排序和非稳定排序

                 // 稳定排序:  能够使任何数值相等的元素,排序以后相对次序不变(只对结构类型数据排序有意义)

                //  非稳定排序:  不是稳定排序的方法

        * 按自然性:               自然排序和非自然排序

                 // 自然排序:  输入数据越有序,排序的速度越快的排序方法

                //  非自然排序:  不是自然排序的方法

          4) 记录序列以顺序表存储

#define MAXSIZE 20                                //设记录不超过20个

typedef int KeyType;                                 //设关键字为int型
typedef char InfoType;                           //设其他数据项为char型
typedef struct                                          //定义每个数据元素的结构
{               
	KeyType key;                                       //关键字
	InfoType otherinfo;                           //其他数据项
}RedType;
typedef struct                                        //定义顺序表的结构
{
	RedType r[MAXSIZE + 1];                   //存储顺序表的向量,r[0]一般作哨兵或缓冲区
	int length;                                         //顺序表的长度
}SqList;

二、插入排序(类似打扑克摸牌)

        1) 基本思想: 每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止

                // 边插入边排序,保证子序列中随时都是排好序的

        2) 基本操作: 有序插入

       * 在有序序列中插入一个元素,保持序列有序,有序长度不断增加

       * 起初,a[0]是长度为1的子序列,然后逐一将a[1]至a[n-1]插入到有序子序列中

       * 在插入a[i]前,数组a的前半段(a[0]~a[i-1])是有序段,后半段(a[i]~a[n-1])是停留于输入次序的"无序段"

       * 插入a[i]使a[0]~a[i-1]有序,也就是要为a[i]找到有序位置j(0<=j<=i),将a[i]插入在a[j]的位置上

        3) 插入排序的分类:

          * 直接插入排序: 顺序法定位插入位置

          * 二分插入排序: 二分法定位插入位置

          * 希尔排序:        缩小增量 多遍插入排序

    1.直接插入排序

      * 顺序表下标为0存哨兵,将每次要比较的元素存入进去(作用是少一次判断,不用判断j是否满足条件,相等直接退出循环)

      * 从顺序表下标为2的元素开始比较(即i的值,i小于等于顺序表元素个数),如果下标为i的元素大于下标为i-1的元素,则i++,否则

           // 将j设为i-1(即最后一个有序值),如果哨兵(即要比较的值)<最后一个有序值,则将下标为j的元素向后移

           // 直到下标j的元素<哨兵(即要比较的值),则将哨兵的值赋给下标为j+1的位置

          // 退出内层循环,i++,继续比较下一个将要插进来的值

void InsertSort(SqList *L)                                 //直接插入排序
{
	int i, j;
	for (i = 2; i <= L->length; i++)
	{
		if (L->r[i].key < L->r[i - 1].key)                //若"<",需将L->r[i]插入有序子表
		{
			L->r[0] = L->r[i];                           //复制为哨兵
			for (j = i - 1; L->r[0].key < L->r[j].key; j--)
			{
				L->r[j + 1] = L->r[j];                   //记录后移
			}
			L->r[j + 1] = L->r[0];                        //插入正确位置
		}
	}
}

     算法分析:

              主要是比较两个关键字的大小及数据元素的移动情况

       1) 最好情况(顺序有序):                   时间复杂度: O(n)

                   比较次数:  n-1(从第二个元素开始比较)

                   移动次数:  0(不需要移动)

       2) 最坏情况(逆序有序):                    时间复杂度: O(n*n)

     

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值