数据结构【选择排序】

排序的基本概念

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

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.o
	gcc -o exe main.c file.c
main.o: main.c file.h
	gcc -Wall -g -c main.c
file.o: file.c file.h
	gcc -Wall -g -c file.c
clean:
	rm exe main.o file.o
  • 创建一个file.c文件用于编写算法程序
  • 创建一个file.h头文件
  • 创建一个main.c文件用于算法的调用和测试
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值