1、排序:重排表中元素。

2、根据数据元素是否完全在内存中,将排序算法分为内部排序和外部排序两类。

3、插入排序:将一个待排序记录按关键字大小插入到前面已排好的子序列中,直到全部记录插入完成。

1)直接插入排序

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[0] = L.r[i];
   L.r[i] = L.r[i - 1];
   for (j = i - 2; 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(1);时间复杂度为O(n2)。

(2)稳定性:插入元素时总是从后向前先比较后移动,不会出现相同元素相对位置发生变化,为稳定算法。

(3)适用性:适用于顺序存储和链式存储的线性表。

2)折半插入排序

void insertsort2(sqlist L)
{
 int i, j, low, high, mid;
 for (i = 2; i < L.length; i++)
 {
  L.r[0] = L.r[i];
  low = 1;
  high = i - 1;
  while (low<=high)
  {
   mid = (low + high) / 2;
   if (L.r[mid].key > L.r[0].key)
   {
    high = mid - 1;
   }
   else
   {
    low = mid + 1;
   }
  }
  for (j = i - 1; j >= high + 1; --j)
  {
   L.r[j + 1] = L.r[j];
  }
  L.r[high + 1] = L.r[0];
 }
}

(1)折半查找找出元素待插入的位置,统一地移动待插入位置之后的所有元素。

(2)时间复杂度为O(n2)。

(3)稳定性:为稳定算法。

3)希尔排序(缩小增量排序)

void insertsort3(sqlist L)
{
 int i, j,k;
 for (j = L.length / 2; j >= 1; j = j / 2)
 {
  for (i = j + 1; i <= L.length; ++i)
  {
   if (L.r[i].key < L.r[i - j].key)
   {
    L.r[0] = L.r[i];
    for (k = i - j; k > 0 && L.r[0].key < L.r[k].key; k -= j)
    {
     L.r[k + j] = L.r[k];
    }
    L.r[k + j] = L.r[0];
   }
  }
 }
}

(1)将待排序表分割成若干个子表,分别进行直接插入排序,当表中元素节本有序时,对整个表进行一次直接插入排序。

(2)空间复杂度为O(1);时间复杂度约为O(n1-2),最坏情况下时间复杂度为O(n2)。

(3)稳定性:不稳定。

(4)适用性:仅适用于顺序存储的线性表。

4、交换排序

1)冒泡排序

void bubblesort(sqlist L)
{
 int i, j, temp;
 bool flag;//发生交换的标志
 for (i = 0; i < L.length-1; i++)
 {
  flag = false;
  for (j = L.length - 1; j > i; j--)
  {
   if (L.r[j - 1].key > L.r[j].key)
   {
    temp = L.r[j - 1].key;
    L.r[j - 1].key = L.r[j].key;
    L.r[j].key = temp;
    flag = true;
   }
  }
  if (flag == false)
  {
   return;
  }
 }
}

(1)从后向前两两比较相邻元素的值,若为逆序则交换。

(2)空间复杂度为O(1);平均时间复杂度为O(n2),最坏情况下时间复杂度为O(n2)。

(3)稳定性:稳定。

(4)双向起泡排序。奇数趟时,从前向后比较相邻元素的关键字,逆序则交换;偶数趟时,从后向前比较相邻元素的关键字,逆序则交换。

void bubblesort2(sqlist L)
{
 int low = 0, high = L.length;
 bool flag = true;
 int temp;
 while (low<high&&flag)
 {
  flag = false;
  for (int i = low; i < high; i++)
  {
   if (L.r[i].key > L.r[i + 1].key)
   {
    temp = L.r[i].key;
    L.r[i].key = L.r[i+1].key;
    L.r[i+1].key = temp;
    flag = true;
   }
  }
  high--;
  for (int i = high; i >low; i--)
  {
   if (L.r[i].key < L.r[i - 1].key)
   {
    temp = L.r[i].key;
    L.r[i].key = L.r[i - 1].key;
    L.r[i - 1].key = temp;
    flag = true;
   }
  }
  low++;
 }
}

2)快速排序

int partition(sqlist L, int low, int high)
{
 int pivotkey;
 L.r[0] = L.r[low];
 pivotkey = L.r[low].key;
 while (low<high)
 {
  while (low<high&&L.r[high].key>=pivotkey)
  {
   --high;
  }
  L.r[low] = L.r[high];
  while (low < high&&L.r[low].key <= pivotkey)
  {
   ++low;
  }
  L.r[high] = L.r[low];
 }
 L.r[low] = L.r[0];
 return low;
}
void quicksort(sqlist L,int low,int high)
{
 if (low < high)
 {
  int pos = partition(L, low, high);
  quicksort(L, low, pos - 1);
  quicksort(L, pos + 1, high);
 }
}

(1)最坏情况空间复杂度为O(n),平均空间复杂度为O(log2n);平均时间复杂度为O(nlog2n),最坏情况下时间复杂度为O(n2)。

(2)所有内部排序中平均性能最优的排序算法。

5、选择排序

每一趟在后面n-i+1个待排序元素中选取关键字最小的元素,作为有序序列的第i个元素,直到第n-1趟做完,待排序元素只剩一个。

1)简单选择排序

void selectsort(sqlist L)
{
 int i, j, min,temp;
 for (i = 0; i < L.length - 1; i++)
 {
  min = i;
  for (j = i + 1; j < L.length; j++)
  {
   if (L.r[j].key < L.r[min].key)
   {
    min = j;
   }
  }
  if (min != i)
  {
   temp = L.r[i].key;
   L.r[i].key = L.r[min].key;
   L.r[min].key = temp;
  }
 }
}

(1)空间复杂度为O(1);时间复杂度为O(n2)。

(2)稳定性:不稳定。

2)堆排序

void adjustdown(sqlist L,int k)//将元素向下调整
{
 L.r[0].key = L.r[k].key;
 for (int i = 2 * k; i <= L.length; i *= 2)
 {
  if (I < L.length&&L.r[i].key < L.r[i + 1].key)
  {
   i++;
  }
  if (L.r[0].key >= L.r[i].key)
  {
   break;
  }
  else
  {
   L.r[k].key = L.r[i].key;
   k = i;
  }
 }
 L.r[k].key = L.r[0].key;
}

时间复杂度与树高(h)有关,为O(h)。
void adjustup(sqlist L, int k)//将元素向上调整
{
 L.r[0].key = L.r[k].key;
 int i = k / 2;
 while (i>0&& L.r[i].key < L.r[0].key)
 {
  L.r[k].key = L.r[i].key;
  k = i;
  i = k / 2;
 }
 L.r[k].key = L.r[0].key;
}

void buildmaxheap(sqlist L)//建立大根堆
{
 for (int i = L.length / 2; i > 0; i--)
 {
  adjustdown(L, i);
 }
}

在n个元素序列上建堆,时间复杂度为O(n)。
void heapsort(sqlist L)
{
 buildmaxheap(L);
 int temp;
 for (int i = L.length; i > 1; i--)
 {
  temp = L.r[i].key;
  L.r[i].key = L.r[1].key;
  L.r[1].key = temp;
  adjustdown(L, 1);
 }
}

(1)一种树形选择排序,在排序过程中,将L视为一棵完全二叉树的顺序存储结构。

(2)最大堆:堆顶元素取最大值;最小堆:栈顶元素为最小值。

(2)空间复杂度为O(1);时间复杂度为O(nlog2n)。

(3)稳定性:不稳定。

6、归并排序

1)归并:将两个或两个以上的有序表组合成一个新的有序表。

2)2路归并排序

void merge(sqlist A, int low, int mid, int high)
{
 sqlist B;
 int i, j, k;
 for (k = low; k <= high; k++)
 {
  B.r[k].key = A.r[k].key;
 }
 for (i = low, j = mid + 1, k = i; i <= mid && j <= high; k++)
 {
  if (B.r[i].key <= B.r[j].key)
  {
   A.r[k].key <= B.r[i++].key;
  }
  else
  {
   A.r[k].key <= B.r[j++].key;
  }
 }
 while (i<=mid)
 {
  A.r[k++].key <= B.r[i++].key;
 }
 while (j <= high)
 {
  A.r[k++].key <= B.r[j++].key;
 }
}
void mergesort(sqlist L, int low, int high)
{
 if (low < high)
 {
  int mid = (low + high) / 2;
  mergesort(L, low, mid);
  mergesort(L, mid + 1, high);
  merge(L, low, mid, high);
 }
}

(1)假定带排序表含有n个记录,则将其视为n个有序的子表,每个子表长度为1,然后两两归并,得到n/2个长度为2或1的有序表,再两两归并,直到合并成一个长度为n的有序表为止。

(2)空间复杂度为O(n);时间复杂度为O(nlog2n)。

(3)稳定性:稳定。

7、基数排序

(1)分类:最高位优先(MSD)、最低位优先(LSD)。

(2)一趟排序需要辅助存储空间为r,空间复杂度为O(r);基数排序需要进行d趟分配和收集,一趟分配需要O(n),一趟收集需要O(r),故基数排序时间复杂度为O(d(n+r)),与序列的初始状态无关。

(3)稳定性:稳定。

8、内部排序的比较

算法种类 时间复杂度 空间复杂度 是否稳定
最好情况 平均情况 最坏情况
直接插入排序 O(n) O(n2) O(n2) O(1)
冒泡排序 O(n) O(n2) O(n2) O(1)
简单选择排序 O(n2) O(n2) O(n2) O(1)
希尔排序       O(1)
快速排序 O(nlog2n) O(nlog2n) O(n2) O(log2n)
堆排序 O(nlog2n) O(nlog2n) O(nlog2n) O(1)
2路归并排序 O(nlog2n) O(nlog2n) O(nlog2n) O(n)
基数排序 O(d(n+r)) O(d(n+r)) O(d(n+r)) O(r)
折半插入排序 O(n2) O(n2) O(n2) O(1)

9、排序小结

1)n较小,采用直接插入排序或简单选择排序。

2)初始状态基本有序,采用直接插入排序或冒泡排序。

3)n较大,采用快速排序、堆排序、归并排序。

4)n较大,关键字位数较少,且可分解,采用基数排序。

10、外部排序通常采用归并排序方法。

1)外部排序所需总时间=内部排序所需时间+外存信息读写时间+内部归并所需时间

2)多路平衡归并

(1)败者树:完全二叉树且不含叶子,可采用顺序存储结构。

3)置换-选择排序:在整个排序过程中,选择最小(或最大)关键字和输入、输出交叉或平行进行。

4)最佳归并树

数据结构(C语言版)---排序的更多相关文章

  1. 数据结构C语言版 表插入排序 静态表

    数据结构C语言版 表插入排序.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情./*  数据结构C语言版 表插入排序  算法10.3 P267-P270  编译 ...

  2. c++学习书籍推荐《清华大学计算机系列教材:数据结构(C++语言版)(第3版)》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <清华大学计算机系列教材:数据结构(C++语言版)(第3版)>习题解析涵盖验证型.拓展型.反思型.实践型和研究型习题,总计290余道大题.525道 ...

  3. 数据结构C语言版 有向图的十字链表存储表示和实现

    /*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...

  4. 数据结构C语言版 弗洛伊德算法实现

    /* 数据结构C语言版 弗洛伊德算法  P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...

  5. 《数据结构-C语言版》(严蔚敏,吴伟民版)课本源码+习题集解析使用说明

    <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明 先附上文档归类目录: 课本源码合辑  链接☛☛☛ <数据结构>课本源码合辑 习题集全解析  链接☛☛☛  ...

  6. 深入浅出数据结构C语言版(17)——有关排序算法的分析

    这一篇博文我们将讨论一些与排序算法有关的定理,这些定理将解释插入排序博文中提出的疑问(为什么冒泡排序与插入排序总是执行同样数量的交换操作,而选择排序不一定),同时为讲述高级排序算法做铺垫(高级排序为什 ...

  7. 深入浅出数据结构C语言版(17)——希尔排序

    在上一篇博文中我们提到:要令排序算法的时间复杂度低于O(n2),必须令算法执行"远距离的元素交换",使得平均每次交换减少不止1逆序数. 而希尔排序就是"简单地" ...

  8. 深入浅出数据结构C语言版(21)——合并排序

    在讲解合并排序之前,我们先来想一想这样一个问题如何解决: 有两个数组A和B,它们都已各自按照从小到大的顺序排好了数据,现在我们要把它们合并为一个数组C,且要求C也是按从小到大的顺序排好,请问该怎么做? ...

  9. 深入浅出数据结构C语言版(22)——排序决策树与桶式排序

    在(17)中我们对排序算法进行了简单的分析,并得出了两个结论: 1.只进行相邻元素交换的排序算法时间复杂度为O(N2) 2.要想时间复杂度低于O(N2),算法必须进行远距离的元素交换 而今天,我们将对 ...

  10. 数据结构(C语言版)严蔚敏->排序

    @ 目录 1. 插入排序 1.1 直接插入排序 1.2 折半插入排序 1.3 希尔排序(Shell Sort) 2.交换排序 2.1 冒泡排序 2.2 快速排序 3. 选择排序 3.1 简单选择排序 ...

随机推荐

  1. swagger2 接口文档,整个微服务接口文档

    1,因为整个微服务会有好多服务,比如会员服务,支付服务,订单服务,每个服务都集成了swagger 我们在访问的时候,不可能每个服务输入一个url 去访问,看起来很麻烦,所以我们需要在一个页面上集成整个 ...

  2. Jupyter修改主题,字体,字号-教程

    cmd控制台安装主题工具包:主题更换工具详解 pip install --upgrade jupyterthemes 查看可用主题: jt -l 设定主题: jt -t 主题名称 恢复默认主题: jt ...

  3. [noip模拟]小猫爬山<迭代深搜>

    [题目描述]: Freda和rainbow饲养了N只小猫,这天,小猫们要去爬山.经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<). Freda和rai ...

  4. 字典树基础进阶全掌握(Trie树、01字典树、后缀自动机、AC自动机)

    字典树 概述     字典树,又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它 ...

  5. Oracle ROWNUM用法

    很多朋友应该跟我一样有个疑问,为什么rownum > 5 的时候会查不到一条数据,用rownum < 5就可以查到数据,明明查询所有的时候rownum有很多啊,小朋友,你是不是有很多问号? ...

  6. Flutter AbsorbPointer 与 IgnorePointer的区别

    AbsorbPointer AbsorbPointer是一种禁止用户输入的控件,比如按钮的点击.输入框的输入.ListView的滚动等,你可能说将按钮的onPressed设置为null,一样也可以实现 ...

  7. man手册、zip备份

                                                                                                        ...

  8. php设计模式总结

    #1 使用设计模式(如建造者.外观.原型和模板模式)更快速.更有效地创建对象 #2 使用数据访问对象和代理设计模式分离体系结构 #3 使用委托.工厂和单元素设计模式改善代码流和控制 #4 在不修改对象 ...

  9. Java第二十九天,文件及目录的管理,File类

    一.基础知识点 1.路径分隔符 (1)什么是路径分隔符? 这个多被应用在环境变量设置当中,例如当我设置Path环境变量时,多个环境变量的路径要用 ':'(Windows系统用封号分隔)或 ':'(Li ...

  10. 创建堆(python)

    创建最大(小)堆 二叉堆本质上是一种完全二叉树,存储方式并不是链式存储,而是顺序存储 堆操作:插入(叶子节点上调),删除(堆顶元素下沉) 堆创建:非叶子节点下沉(从最后一个非叶子节点开始) 最小堆: ...