排序算法实现
来源:互联网 发布:淘宝网出售二手床 编辑:程序博客网 时间:2024/06/03 19:28
排序算法实现
前言
最近处理数据时常会用到排序算法,故有整理各种排序算法的想法。博客中有很多非常好的文章排序算法介绍及实现,但经常发现其实现代码并不能很好的运行,或多或少都会有bug,故写下以下文章总结一下各算法中需要注意的问题。
插入排序
直接插入排序
算法思想:将记录逐个插入到已存在的有序表中,从而得到一个新的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序。
示意图
图1 直接插入排序
算法实现(Python实现)
第一版
class InsertSort(object): def __init__(self): return def sort(self, mlist): # mlist为待排序列表(数组) for count in xrange(1, len(mlist)): index = count - 1 # index待比较位置, index+1为待插入位置 ele = mlist[count] # 复制为哨兵x,即存储待排序元素 if ele > mlist[count - 1]: continue # 若待插入大于序列最后一个元素,直接插入。 while(ele < mlist[index]): mlist[index + 1] = mlist[index] # 若ele小于待插入位置的元素则后移 index = index - 1 # 继续向左比较直到找到比ele大的元素(索引index),插入index+1位置 mlist[index + 1] = ele # 插入到正确位置if __name__ == '__main__': myList = [3, 1, 5, 7, 2, 4, 9, 6] mInsertSort = InsertSort() mInsertSort.sort(myList) print myList
以上代码描述了插入排序算法的基本动作,但仔细看会发现这段代码并不能很好的运行:在ele比较插入位置时,若比序列中第一个元素还要小,索引index继续左移很显然逻辑错误。
第二版
class InsertSort(object): def __init__(self): return def sort(self, mlist): print mlist for count in xrange(1, len(mlist)): index = count - 1 # index待比较位置, index+1为待插入位置 ele = mlist[count] # 复制为哨兵x,即存储待排序元素 if ele > mlist[count - 1]: print(mlist, ele, count) continue # 若第i个元素大于i-1元素,直接插入。 while(ele < mlist[index] and index >= 0): mlist[index + 1] = mlist[index] # 若ele小于待插入位置的元素则后移 index = index - 1 # 继续向左比较 mlist[index + 1] = ele # 插入到正确位置 print(mlist, ele, count) # 打印每趟排序的结果 if __name__ == '__main__': myList = [3, 1, 5, 7, 2, 4, 9, 6] mInsertSort = InsertSort() mInsertSort.sort(myList) print myList
在while循环中加入index >= 0的限制index取值,当待插入值比序列第一个元素还要小则插入当前位置.
效率分析
直接插入算法中基本操作(可理解为最内层循环执行的语句)的频度与待排序序列长度N成平方关系,则时间复杂度为O(N^2)。很显然对于这种算法效率并不是很高,下文介绍另一种插入排序算法(希尔排序)能很好提高效率。
希尔排序
算法思想:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量 =1( < …<d2<d1),即所有记录放在同一组中进行直接插入排序为止。希尔排序实质是分组插入方法。
示意图
图2 希尔排序
算法实现(Python实现)
class ShellSort(object):
def __init__(self): return def insertSort(self, mlist, div): for count in xrange(div, len(mlist)): # 取分组序列 index = count - div # index待比较位置, index+1为待插入位置 ele = mlist[count] # 复制为哨兵x,即存储待排序元素 if ele > mlist[count - div]: print(mlist, ele, count) continue # 若第i个元素大于i-1元素,直接插入。 while(ele < mlist[index] and index >= 0): mlist[index + div] = mlist[index] # 若ele小于待插入位置的元素则后移 index = index - div # 继续向左比较 mlist[index + div] = ele # 插入到正确位置 print(mlist, ele, count) # 打印每趟排序的结果 return def shellSort(self, mlist): for div in xrange(len(mlist), 0, -1): self.insertSort(mlist, div) returnif __name__ == '__main__': myList = [3, 1, 5, 7, 2, 4, 9, 6] mInsertSort = ShellSort() mInsertSort.shellSort(myList) print myList
另一种实现
import randomclass ShellSort(object): def __init__(self): return def insertSort(self, mlist, div): for head in xrange(0, div): for count in xrange(head, len(mlist), div): # 取分组序列 index = count - div # index待比较位置, index+div为待插入位置 ele = mlist[count] # 复制为哨兵x,即存储待排序元素 if ele > mlist[count - div]: print(mlist, ele, count) continue # 若第i个元素大于i-div元素,直接插入。 while(ele < mlist[index] and index >= 0): mlist[index + div] = mlist[index] # 若ele小于待插入位置的元素则后移 index = index - div # 继续向左比较 mlist[index + div] = ele # 插入到正确位置 print(mlist, ele, count) # 打印每趟排序的结果 def shellSort(self, mlist): for div in xrange((len(mlist) / 2) + 1, 0, -1): self.insertSort(mlist, div) returnif __name__ == '__main__': myList = list() for count in xrange(100): myList.append(random.randint(1, 100)) mInsertSort = ShellSort() mInsertSort.shellSort(myList) print myList
以上两种代码实现思路相似,只是第二种更接近图片描述的先分组再排序。
效率分析
希尔排序基于插入排序算法, 在此算法基础之上增加了分组特性,提高了效率。希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(n^(2/3)),希尔排序时间复杂度的下界是n*log2n。希尔排序没有快速排序算法快 O(n(logn)),因此中等大小规模表现良好,对规模非常大的数据排序不是最优选择,但是比O(n^2 )复杂度的算法快得多。
希尔排序非常容易实现,算法代码短而简单。 此外,希尔算法在最坏的情况下和平均情况下执行效率相差不是很多,与此同时快速排序在最坏的情况下执行的效率会非常差。专家们提倡,几乎任何排序工作在开始时都可以用希尔排序,若在实际使用中证明它不够快,再改成快速排序这样更高级的排序算法. 本质上讲,希尔排序算法是直接插入排序算法的一种改进,减少了其复制的次数,速度要快很多。 原因是,当n值很大时数据项每一趟排序需要的个数很少,但数据项的距离很长。当n值减小时每一趟需要和动的数据增多,此时已经接近于它们排序后的最终位置。 正是这两种情况的结合才使希尔排序效率比插入排序高很多。Shell算法的性能与所选取的分组长度序列有很大关系。只对特定的待排序记录序列,可以准确地估算关键词的比较次数和对象移动次数。想要弄清关键词比较次数和记录移动次数与增量选择之间的关系,并给出完整的数学分析,至今仍然是数学难题。(摘自百度百科)
选择排序
直接选择排序
算法思想
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
示意图
图3 简单选择排序
算法实现(Python实现)
简单插入排序
class selectSort(object): def __init__(self): return def sort(self, data): """选择排序 """ for sortCount in range(len(data)): min = sortCount # 待排序序列最小值索引 for index in range(sortCount, len(data)): # 获取待排序序列最小值索引 if data[index] < data[min]: min = index data[sortCount], data[min] = data[min], data[sortCount] print '第%s趟排序' %sortCount, dataif __name__ == '__main__': data = [94, 13, 83, 23, 65, 63, 15, 27, 48, 39] selectSort = selectSort() selectSort.sort(data)
二元选择排序
class selectSort(object): def __init__(self): return # 简单选择排序 def sort1(self, data): """选择排序 """ for sortCount in xrange(len(data)): min = sortCount # 待排序序列最小值索引 for index in xrange(sortCount, len(data)): # 获取待排序序列最小值索引 if data[index] < data[min]: min = index data[sortCount], data[min] = data[min], data[sortCount] print '第%s趟排序' %sortCount, data # 二元选择排序 def sort(self, data): for sortCount in xrange(len(data) / 2): min = sortCount # 待排序序列最小值索引 max = len(data) - sortCount - 1 # 待排序序列最大值索引 for index in xrange(sortCount, len(data) - sortCount): # 获取待排序序列最小值索引 if data[index] < data[min]: min = index continue if data[index] > data[max]: max = index # 这里不能直接交换,因为交换会改变数组值造成索引指向偏离预期的值 # 错误的做法# data[sortCount], data[min] = data[min], data[sortCount]# data[len(data) - sortCount - 1], data[max], = data[max], data[len(data) - sortCount - 1] # 正确的做法 data[sortCount], data[min] = data[min], data[sortCount] if max == sortCount: max = min data[len(data) - sortCount - 1], data[max], = data[max], data[len(data) - sortCount - 1] print '第%s趟排序' %sortCount, dataif __name__ == '__main__': data = [94, 13, 83, 23, 65, 63, 15, 27, 48, 39] selectSort = selectSort() selectSort.sort(data)
效率分析
直接选择排序和二元选择排序时间复杂度为O(N^2),下文介绍简单选择排序改进算法“堆排序”。
待更新
- 【排序】内部排序算法实现
- 快速排序算法实现
- 排序算法的实现
- 实现选择排序算法
- 排序算法java实现
- 快速排序算法实现
- 排序算法的实现
- 合并排序 算法实现
- 快速排序算法实现
- 排序算法实现大全
- 基本排序算法实现
- 排序算法JS实现
- 排序算法python实现
- 各排序算法实现
- 堆排序算法实现
- 交换排序算法实现
- 排序算法实现
- 全排序算法实现
- redis.conf配置文件解析
- wpa_supplicant wifi密码错误检测
- InputStream类的available()方法获取流的长度
- ProgressDialog(进度条)
- java 初始化及执行顺序
- 排序算法实现
- 为什么RSA 公钥指数(e=65537)
- try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
- 前端web开发的MVC模式
- FFmpeg编译ios平台
- 都说Djnago框架重,那就让哥用15行代码写个django web程序!
- MATLAB数学建模(9)-遗传算法工具
- Java基础-面向对象小知识(上)
- 液晶设计参数确定