5.2 排序
排序(sorting)是将一系列数据进行重组的过程。
5.2.1 冒泡排序
冒泡排序(bubble sort),是对含n个元素的序列s进行n-1轮遍历(假定要进行升序排列),每一轮遍历,如果s[i] > s[i+1],那么交换两者的值,这样第一轮就可以确保最大的元素排在末尾,第二轮可以确定次大的元素可以排在倒数第二的位置,依次类推。
#-*-coding: utf-8-*-
# 冒泡排序的实现,其复杂度是O(n²)
def bubbleSort(theSeq):
n = len(theSeq)
for i in range(n - 1):
for j in range(n - i - 1):
if theSeq[j] > theSeq[j+1]:
theSeq[j], theSeq[j+1] = theSeq[j+1], theSeq[j]
print theSeq
冒泡排序的最坏情况是将一个降序序列排序成升序序列,其时间复杂度是O(n²)。冒泡排序是效率较低的排序算法。
5.2.2 选择排序
选择排序(selection sort),是对含n个元素的序列s,进行n-1轮遍历,它将序列分成已排序和未排序两部分,已排序在前,未排序在后,注意是对未排序部分进行遍历。第一轮遍历中,先找出这n个元素的最小值,并置于首项,作为已排序部分的第一项,第二轮遍历中,找出剩下的n-1个元素的最小值,并置于第二项,依次类推。
#-*-coding: utf-8-*-
# 选择排序的实现,时间复杂度同样还是O(n²),但是降低了每一次循环的交换次数
def selectionSort(theSeq):
n = len(theSeq)
for i in range(n - 1):
smallNdx = i # 先假设最小值的索引是i
for j in range(i + 1, n): # 假设的最小值与后面的值相比较
if theSeq[j] < theSeq[smallNdx]: # 如果有比假设的最小值还小的数值,将该索引标记
smallNdx = j
if smallNdx != i: # 最小值索引发生改变,就进行交换
theSeq[i], theSeq[smallNdx] = theSeq[smallNdx], theSeq[i]
print theSeq
选择排序是在冒泡排序的基础上进行的改进,虽然同样要进行n-1轮遍历,但是每一轮遍历都只有一次交换。其时间复杂度仍然是O(n²)。
5.2.3 插入排序
插入排序(insertion sort),是对含n个元素的序列s,进行n-1轮遍历,也是讲序列分成已排序和未排序两部分,已排序在前,未排序在后,注意是对已排序部分进行遍历。已排序部分默认将第一项作为初始状态,在第一轮遍历中,将第二项,与第一项进行比较,插入到合适的位置,第二轮遍历中,将第三项与前两项进行比较,插入到合适的位置,依次类推。
#-*-coding: utf-8-*-
# 插入排序的实现
def insertionSort(theSeq):
n = len(theSeq)
for i in range(1, n): # 将第一个元素作为已排序部分
value = theSeq[i] # 先将要插入的元素的值先保存
pos = i # 插入元素的正确插入位置,先假设为原来位置,这里也是已排序部分和未排序部分的分界点
while pos > 0 and value < theSeq[pos - 1]: # 这里遍历的是已排序部分
theSeq[pos] = theSeq[pos - 1] # 在搜索过程中,将大于插入元素的项右移一位
pos -= 1
theSeq[pos] = value # 找到正确插入位置,将之前保存的值赋值
print theSeq
插入排序与选择排序的主要区别是遍历对象的不同,前者是对已排序部分进行遍历,而后者是对未排序部分进行遍历。其时间复杂度依旧是O(n²)。