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. python框架-Django创建项目

    创建项目 django-admin startproject douban//创建project cd douban python manage.py startapp books//创建app项目 ...

  2. 加密解密 Python

    常见加密方式和Python实现 1. 前言 我们所说的加密方式,都是对二进制编码的格式进行加密的,对应到Python中,则是我们的Bytes. 所以当我们在Python中进行加密操作的时候,要确保我们 ...

  3. [vijos1883]月光的魔法<递归>

    题目链接:https://vijos.org/p/1883 这道题还有另外一种版本叫天神下凡,属于模拟题,可是模拟题数据太水以至于模拟题A了都不一定在vijos上A.... 在模拟题里我用的是一种类似 ...

  4. Java实现3次找到假球

    前言 之前老师让写一个程序,就写了写. 正文 题目要求 程序要求 10个铅球中有一个假球(比其他铅球的重量要轻),用天平三次称出假球. 程序设计思路 第一次使用天平分别称5个球,判断轻的一边有假球:拿 ...

  5. node.js 实现接口-操作文件进行用户增删改查

    首先安装npm,使用npm安装express npm install express -S /* * @Author: yinxin * @Date: 2020-03-27 10:18:41 * @L ...

  6. 四、【Docker笔记】Docker容器

    容器是Docker的另一个核心概念,容器就是镜像的一个运行实例,只是它具有一个可写的文件层,而镜像是一个只读的文件. 一.创建容器 1.新建容器 我们可以使用 docker create 命令来创建一 ...

  7. vulnhub~DC-9

    首先对于整体的思路,网上有很多的教程,如果国内的不能满足建议‘fanqiang’,Google有很多大佬,各个部分都有详细的说明.但又由于每个人的环境都有所不同,所以会在同样的命令行执行后出现不同的错 ...

  8. mysql物理结构

    MySQL是通过文件系统对数据和索引进行存储的. MySQL从物理结构上可以分为日志文件和数据索引文件. MySQL在Linux中的数据索引文件和日志文件都在/var/lib/mysql目录下. 日志 ...

  9. Vlan间通讯,动态路由

    Vlan间通讯,动态路由 案例1:三层交换vlan间通信 案例2:多交换机vlan间通信 案例3:三层交换配置路由 案例4:RIP动态路由配置 案例5:三层交换配置RIP动态路由 1 案例1:三层交换 ...

  10. 曹工说Redis源码(3)-- redis server 启动过程完整解析(中)

    文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...