排序的基本概念

在排序中结点(数据元素)称为“记录”, 记录的集合称为 “文件”,内存中文件也常称为“线性表”。

1.排序(Sorting):

排序(Sorting) 是按关键字的 非递减或非递增顺序 对一组记录 重新进行排列的操作

所谓排序就是将原本无序的序列重新排成有序的序列。在这个序列中的每一项可能是一个数据元素,也可能是一条记录(由多个数据元素构成组成的,例如一个学生的信息是由学号,姓名,性别,年龄等组成)。
如果是记录,则可以按照主关键字进行排序(例如一个学生的学号是唯一的用来标识学生身份的主关键字),也可以按照次关键字进行排序(如一个学生的姓名,年龄,性别等都是次关键字,并且次关键字可能会重复)。

2.内部排序 和 外部排序:

由于待排序记录的数量不同,使得排序过程中数据所占用的存储设备会有所不同。根据在排 序过程中记录所占用的存储设备,可将排序方法分为两大类:一类是内部排序指的是待排序记录全部存放在计算机内存中进行排序的过程;另一类是外部排序指的是待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中尚需对外存进行访问的排序过程

内部排序 是指 ,记录序列在计算机内存中进行排序的过程;
外部排序 是指,由于待排序记录的数量庞大,内存一次不能容纳所需排序的内容,需要从外存中访问记录完成排序的过程。

3.排序的稳定性:

当排序记录中的关键字K;(i = 1, 2, …, n) 都不相同时, 则任何一个记录的无序序列经排序后得到的结果唯一;反之,当待排序的序列中存在两个或两个以上关键字相等的记录时, 则排序所得的结果不唯一。

当待排序序列中出现了两个或两个以上的相同的关键字时,排序前后这些关键字的相对位置没有发生变化就是稳定的,如果发生了变化就是不稳定的。
例如,序列中有两个关键字都是100,那么用100(a)和100(b)来区分他们,用一种算法对它进行了排序之后,100(a)排在100(b)之前,那么这种算法就是稳定的,但是如果在某种情况下100(a)排在了100(b)之后,那么这种算法就是不稳定的。
如果在这个序列里关键字不会重复,那排序的结果是唯一的,算法的稳定性就显得没那么重要了;如果算法的关键字可以重复,那么就需要考虑一种稳定的排序算法。

排序算法效率的评价指标

前面已指出,就排序方法的全面性能而言,很难提出一种被认为是最好的方法。目前,评价排序算法好坏的标准主要有两点。
(1) 执行时间
对于排序操作,时间主要消耗在关键字之间的比较记录的移动上(这里只考虑以顺序表方式存储待排序记录),排序算法的时间复杂度由这两个指标决定。因此可以认为,高效的排序算法的比较次数和移动次数都应该尽可能的少
(2)辅助空间
空间复杂度由排序算法所需的辅助空间决定。辅助空间是除了存放待排序记录占用的空间之外,执行算法所需要的其他存储空间。理想的空间复杂度为 0(1), 即算法执行期间所需要的辅助空间与待排序的数据量无关。

待排序记录的存储方式

(1) 顺序表:记录之间的次序关系由其存储位置决定,实现排序需要移动记录。
(2) 链表:记录之间的次序关系由指针指示,实现排序不需要移动记录,仅需修改指针即可。 这种排序方式称为链表排序
(3) 待排序记录本身存储在一组地址连续的存储单元内,同时另设一个指示各个记录存储位置的地址向量,在排序过程中不移动记录本身,而移动地址向撒中这些记录的”地址 “,在排序结束之后再按照地址向量中的值调整记录的存储位置。这种排序方式称为地址排序

内部排序方法的分类

内部排序的方法很多,但就其全面性能而言,很难提出一种被认为是最好的方法,每一种方 法都有各自的优缺点,适合在不同的环境(如记录的初始排列状态等) 下使用。
内部排序的过程是一个逐步扩大记录的有序序列长度的过程。在排序的过程中,可以将排序记录区分为两个区域:有序序列区无序序列区
使有序区中记录的数目增加一个或几个的操作称为一趟排序
根据逐步扩大记录有序序列长度的原则不同,可以将内部排序分为以下几类。
(1) 插入类:将无序子序列中的一个或几个记录“插入”到有序序列中,从而增加序列的有序子序列的长度。主要包括直接插入排序、折半插入排序和希尔排序
(2) 交换类:通过“交换”无序序列中的记录从而得到其中关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。主要包括冒泡排序和快速排序
(3) 选择类:从记录的无序子序列中“选择”关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。主要包括简单选择排序、树形选择排序和堆排序
(4) 归并类:通过“归并”两个或两个以上的记录有序子序列,逐步增加记录有序序列的长度。2-路归并排序是最为常见的归并排序方法
(5)分配类:是唯一一类不需要进行关键字之间比较的排序方法,排序时主要利用分配和收
集两种基本操作来完成。基数排序是主要的分配类排序方法

选择排序

【算法步骤】
(1)设待排序的记录存放在数组r[1…n]中。第一趟从 r[1] 开始,通过n-1次比较,从n个记录中选出关键字最小的记录,记为r[k], 交换 r[1] 和 r[k]。
(2)第二趟从 r[2] 开始,通过n-2次比较,从n-1个记录中选出关键字最小的记录,记为 r[k], 交换 r[2] 和 r[k] 。
(3)依次类推,第 i 趟从 r[i] 开始,通过 n-i 次比较,从 n-i+1 个记录中选出关键字最小的记录,记为 r[k], 交换 r[i] 和 r[k]。
(4)经过n-1趟,排序完成。

举例:
初始: {8,6,7,14,2,5,9}
i = 1: {2,6,7,14,8,5,9}
i = 2: { 2,5,7,14,8,6,9}
i = 3: {2,5,6,14,8,7,9}
i = 4: {2,5,6,7,8,14,9}
i = 5: {2,5,6,7,8,14,9}
i = 6: {2,5,6,7,8,9,14}

总结一下,就是在一个序列里从第一个位置开始依次固定一个位置并从这个位置之后的所有元素里找一个最小值来替换这个位置的元素。

时间复杂度:简单选择排序所需进行记录移动的次数较少,最好的情况(正序):不移动;最坏的情况(逆序):移动3(n-1)次。无论记录的初始排序序列如何,记录间的比较次数相同。因此,简单选择序列的时间复杂度为O(n²)。

空间复杂度:只有在两个交换过程中需要一个辅助空间,因此,简单选择排序的空间复杂度为O(1)

下面进行程序设计:

【先编译一个makefile文件】

exe: file.o main.ogcc -o exe main.c file.c
main.o: main.c file.hgcc -Wall -g -c main.c
file.o: file.c file.hgcc -Wall -g -c file.c
clean:rm exe main.o file.o
  • 创建一个file.c文件用于编写算法程序
  • 创建一个file.h头文件
  • 创建一个main.c文件用于算法的调用和测试

1.1【首先写一个void swap(int * a, int * b)函数来交换a和b的值】

void swap(int * a, int * b)
{int t;t = *a;*a = *b;*b = t;
}

1.2【用swap作为子程序编写选择排序的程序】

void SelectionSort(int * T, int N)/* N is the amount of the list */
{int k, i, j;for (i = 0; i < N - 1; ++i)/* check the list to find the minimum */{k = i;for (j = i + 1; j < N; ++j){if (T[j] < T[k])k = j;}swap(&T[k], &T[i]);}
}

1.3【测试编写的程序】

#include <stdio.h>
#include "file.h"int main()
{int i, N = 10;int T[10] = {10,5,2,4,8,16,7,3,6,9};SelectionSort(T, N);for (i = 0; i < N; i++){printf("%d ", T[i]);}printf("\n");return 0;
}

执行结果如图所示:

1.4【在特殊情况下测试程序】

1.4.1 数组已经升序

#include <stdio.h>
#include "file.h"int main()
{int i, N = 10;int T[10] = {1,2,3,4,5,6,7,8,9,10};SelectionSort(T, N);for (i = 0; i < N; i++){printf("%d ", T[i]);}printf("\n");return 0;
}

执行结果如图所示:

1.4.2 数组已经降序

#include <stdio.h>
#include "file.h"int main()
{int i, N = 10;int T[10] = {10,9,8,7,6,5,4,3,2,1};SelectionSort(T, N);for (i = 0; i < N; i++){printf("%d ", T[i]);}printf("\n");return 0;
}

执行结果如图所示:

1.4.3 只有一个元素的数组

#include <stdio.h>
#include "file.h"int main()
{int i, N = 1;int T[] = {1};SelectionSort(T, N);for (i = 0; i < N; i++){printf("%d ", T[i]);}printf("\n");return 0;
}

执行结果如图所示:

1.4.4 数组几乎排序,但在开头和结尾有错位

#include <stdio.h>
#include "file.h"int main()
{int i, N = 10;int T[] = {100,2,3,4,5,6,7,8,9,1};SelectionSort(T, N);for (i = 0; i < N; i++){printf("%d ", T[i]);}printf("\n");return 0;
}

执行结果如图所示:

1.5【编写一个过程,用0到99之间的随机值填充一个整数数组】

void fillRandom(int N, int * T)
{int i;for (i = 0; i < N; ++i)T[i] = rand() % 100;
}

【 rand()函数是<stdlib.h>标准库里的C函数,它返回 0 和 rand_Max 之间伪随机数。】

1.6【在 main() 函数中用随机值初始化一个由10个整数组成的数组,并显示它,按选择排序进行排序。】

#include <stdio.h>
#include "file.h"int main()
{int i, N = 10;int T[10];fillRandom(N, T);SelectionSort(T, N);for (i = 0; i < N; i++){printf("%d ", T[i]);}printf("\n");return 0;
}

执行结果如图所示:

1.7【对大小为1000、10000和100000的数组执行相同的操作】

1.7.1 大小为1000的数组

#include <stdio.h>
#include "file.h"int main()
{int i, N = 1000;int T[1000];fillRandom(N, T);SelectionSort(T, N);for (i = 0; i < N; i++){printf("%d ", T[i]);}printf("\n");return 0;
}

伪随机数的范围也要扩大:

void fillRandom(int N, int * T)
{int i;for (i = 0; i < N; ++i)T[i] = rand() % 10000;
}

展示数组范围为1000的结果:

数据结构【选择排序】相关推荐

  1. 数据结构------选择排序

    数据结构------选择排序 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> void simpleSelectSor ...

  2. 数据结构-选择排序(简单选择排序,堆排序)

    目录 1,简单选择排序 1.1,简单选择排序思想 1.2,选择排序的时间复杂度分析 1.3,简单选择排序代码实现 2,堆排序 2.1,什么是堆排序 2.2,堆排序的思想 2.3,堆排序时间复杂度分析 ...

  3. 数据结构---选择排序(直接选择排序和堆排序图解)

    选择排序思想: 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的 数据元素排完 . 直接选择排序 在元素集合array[i]–array[n-1]中选择关 ...

  4. 数据结构:选择排序(Selection sort)

    package com.sortbasic;import java.util.Random;public class SelectionSortGenerate {// 数组private stati ...

  5. 数据结构--选择排序

    选择排序的一种Go实现 package mainimport "fmt"//选择排序的核心是第n次将数组中后面len(arr) - n个元素的最大或者最小值与第n个元素进行交换 f ...

  6. python算法与数据结构-选择排序算法

    代码如下所示: # 定义选择排序函数 def select_sort(list):# 计算需要排序的列表元素个数n = len(list)# 需要n-1次选择操作for j in range(n - ...

  7. python算法与数据结构-选择排序算法(33)

    阅读目录 一.选择排序的介绍 二.选择排序的原理 三.选择排序的图解 四.选择排序总结 五.选择排序的python代码实现 六.选择排序的C语言代码实现 七.选择排序的时间复杂度 八.选择排序的稳定性 ...

  8. 浅谈数据结构-选择排序(简单、堆排序)

    选择排序:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止. 选择排序正如定义所讲,在数组查询出最小值,然后放在此次循环开始位置(前一次循环已经获取比它更小 ...

  9. 数据结构-选择排序(Python)

    假设你的计算机存储了很多乐曲.对于每个乐队,你都记录了其作品被播放的次数. 你要将这个列表按播放次数从多到少的顺序排列,从而将你喜欢的乐队排序.该如何做呢? 一种办法是遍历这个列表,找出作品播放次数最 ...

  10. 数据结构与算法:选择排序

    数据结构与算法:选择排序 雪柯 大工生物信息 提笔为写给奋进之人 已关注 8 人赞同了该文章 引用自算法图解,作者[美] Aditya Bhargava 译袁国忠 特别备注:本书非原创,但部分内容自己 ...

最新文章

  1. mass Framework pagination插件
  2. Linux 卸载分区(会格式化分区数据)
  3. VTK:图片之ImageMagnitude
  4. IPTABLES封闭和开放端口
  5. 网络知识:路由器不关闭这个功能,视频越刷越卡!
  6. leetcode 1047. 删除字符串中的所有相邻重复项(栈)
  7. 2021浙江高考首考成绩查询,浙江2021选考成绩什么时候出成绩?附2021浙江学考成绩查询时间...
  8. bat命令 (参数传递)
  9. 计算机基本知识(8000)---boot系统引导文件
  10. DRP:分销链上的精灵(转)
  11. Windows XP和Windows 7双系统安装说明和注意事项
  12. java相关优秀博文收藏
  13. mac下面如何修改只读文件
  14. 结对项目-数独程序扩展
  15. 3599元起 铭凡推出NPB7迷你主机:i7-13700H、双雷电4
  16. 一个额外的小问题——关于jdk和Language level的关系
  17. 通过数据可视化进行足球进球方式分析球员属性
  18. 涉黄网站爆四大生财链:站长月入近两万
  19. 出租车不需要司机了?带你体验无人驾驶出租车!|『智能产品家』第三期
  20. 于宙:我们这一代人的困惑

热门文章

  1. python二级练习软件(90%原题)题库、三天速成。
  2. 基于讯飞语音云的Android语音识别与朗读
  3. 【专利查询、下载及撰写】
  4. 宝石TD新手进阶资料
  5. AMD fx4300,FX系列的CPU有核显吗
  6. [计算机网络笔记06] 集线器和交换机的区别
  7. cmd解决javac报错
  8. 曾经的经典玄幻小说(二)
  9. win10进lol无法连接服务器未响应,Win10 64位系统电脑中lol游戏无法连接服务器的处理方法...
  10. docker containerd 架构和源码简单分析