排序算法的基本概念
根据排序过程中待排序文件存放的位置不同,可以把排序分为内部和外部排序两大类。在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序;在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序。内部排序适用于记录个数不很多的较小待排序文件的排序;外部排序则适用于记录个数太多不能一次全部放入内存的较大待排序文件的排序。
内部排序分类
- 交换排序:常用的交换排序方法有冒泡排序和快速排序。
- 选择排序:常用的选择排序方法有直接选择排序、树型选择排序和堆排序。
- 插入排序:主要的插入排序方法有直接插入排序、希尔排序、二分法插入排序、二路插入排序和共享栈插入排序等。
- 归并排序
- 基数排序
概念解释:
冒泡排序
- 重复遍历序列,每次遍历都要将相邻两个数中较大的一个向后移动,直至有序为止。
- 特点:简单。多次移动。当序列
快速排序
- 遍历序列,每个元素将序列分割成两部分(小于他和大于他),当遍历结束时,序列有序。
- 特点:时间和空间复杂度较低。但是当元素基本有序时,时间与冒泡排序相同。
class Sort:
@classmethod
def sort(cls, arr):
cls.sortQuick(arr, 0, len(arr) -1)
@classmethod
def sortQuick(cls, arr, lo, hi):
if lo >= hi:
return
p = cls.position(arr, lo, hi)
cls.sortQuick(arr, lo, p)
cls.sortQuick(arr, p+1, hi)
@classmethod
def position(cls, arr, lo, hi):
v = arr[lo]
i = lo
j = hi
while True:
while i < hi and arr[i] <= v:
i += 1
while j > lo and arr[j] >= v:
j -= 1
if i >= j:
break
else:
arr[i], arr[j] = arr[j], arr[i]
arr[lo], arr[j] = arr[j], arr[lo]
return j
选择排序
- 每次将原序列中最小的插入到新序列的最后。
- 特点:交换的次数最少,运行时间与输入的元素顺序无关。
def sortSelect(arr):
n = len(arr)
for i in range(0, n):
min = i;
for j in range(i+1, n):
if arr[j] < arr[i]:
min = j
else:
pass
temp = arr[i]
arr[i] = arr[min]
arr[min] = temp
插入排序
- 遍历序列,将序列插入一个基本有序的序列,每插入一个序列,都要保证插入序列有序。
- 特点:所需时间取决于输入元素的初始顺序,适用于一个很大且其中元素基本有序的数组。
def sortInsert(arr):
n = len(arr)
for i in range(1, n):
j = i
while j > 0 and arr[j] < arr[j - 1]:
arr[j], arr[j-1] = arr[j-1], arr[j]
j = j - 1
堆排序
- 数中任意非叶子节点的关键字均不大于(或不小与)其左右孩子节点的关键字。
- 特点:由于建初始堆所需要的比较次数较多,所以不适宜记录数较少的文件。由于它是树形结构,所以不能存储较多节点。此外,它还是一颗完全二叉树。这样就可以用数组转储,就可以用来存储较多的数据。
桶排序
- 根据关键字的特点,将关键字置于不同的桶中,然后对每个小桶进行排序,最后将结果合并。
- 特点:序列应该尽可能的分布在均匀的线性分布。由于不需要将数据一次性全部调入内存,因此适用于海量数据排序。
排序方法的比较
1.时间性能比较
- nlog2n : 二路归并排序、堆排序和快速排序
- 1.5n : 希尔排序O
- n^2 : 插入、冒泡、选择
2.辅助空间的比较
- n : 二路归并排序、桶排序
- 1:其他排序.
3.稳定性比较
- 稳定:插入排序、冒泡排序、二叉树排序、二路归并排序、桶排序。
- 不稳定:选择排序、希尔排序、快排、堆排序。