最近在学数据结构里的排序,主要接触了冒泡排序,选择排序,插入排序,希尔排序,快速排序,基数排序还有堆积排序,然后用python语言写出了它们的具体实现方法,为了增强记忆,下面用自己最容易理解的语言再把它们总结一遍吧!
**—以下的各种排序算法我从是基于从小到大排序来进行的— **
1. 冒泡排序
冒泡排序就是从第一个元素开始,逐个比较与相邻元素的顺序,顺序不正确的话就对调,一直到最后一个元素。就像水里的泡泡咕噜咕噜上升到水面上一样…
比如一个无序数组:[9,8,7,66,55,4,3,2,1]
从第一个数9开始,比8大,不对,那就对调;这时第二个数是9了,和第三个数7比,不对,再对调。这样比下去的话,一个数只要比它前面的数大就会不停后移,一路比到最后,结果就是这个数组里最大的那个元素被送到了最后一位。我们要排序的这个数组一共9位数,第一个步骤后已经成功了1/9,emmmmm…
接下来最后一位我们不用管了,它已经是正确的了,再看前8位数吧,用上面同样的方式一路比下去,又顺利地把数组第二大的数送到了倒数第二个位置。好了,现在成功了2/9啦
这样一直重复下去,直至从后往前,每一个位置都被放上了正确的数字,排序完成
基于这个思路,写出python程序如下:
qq=[9,8,7,46,33,4,3,2,1]
print('初始排序是'+str(qq))
for i in range(int(len(qq)-1),-1,-1):
for j in range(i):
if qq[j]>qq[j+1]:
qq[j],qq[j+1]=qq[j+1],qq[j]
print('第'+str(len(qq)-i)+'次排序结果是:'+str(qq))
print('最终排序结果是'+str(qq))
但是有一个问题,比如我们要进行排序的数组是[1,2,3,5,4],第一轮就能使整个数组排序正确,但是上面的代码还是会继续循环3次才结束,后面就是再做无用功了,很没效率!怎么办
qq=[1,2,3,7,6]
print('初始顺序是:'+str(qq))
for i in range(len(qq)-1,-1,-1):
flag=0
for j in range(i):
if qq[j]>qq[j+1]:
qq[j],qq[j+1]=qq[j+1],qq[j]
flag=flag+1
if flag==0:
break
print('第'+str(len(qq)-i)+'次排序的结果是:'+str(qq))
#注意:print结果一定要放在break后面,否则还会多打印一轮冗余结果
print('最终的排序结果是'+str(qq))
基于前面的代码,加了一个flag,每一轮循环完如果flag仍然是0,说明这一轮循环并没有做任何改变,说明数组已经被正确排序了,那就可以终止循环得到最终结果
总结:冒泡排序是从后往前依次放入正确排序的元素
2.选择排序
我感觉选择排序和冒泡排序的思路正好相反,先选择最小的数放在第一个位置,然后选择第二小的数放在第二个位置,这样依次重复下去直至得到排序好的数组…
具体是这样的:还是从第一个元素开始,让它分别跟后面的所有元素作比较,如果大于谁了,就把谁给换到第一个位置来,这样比完一轮的结果是最小的元素成功被放到了第一个位置
下面再从第二个位置开始,也是同样的思路,比完一轮后第二小的元素被放到了第二个位置
按照同样的方式一直到倒数第二个元素也比完了,这样整个数组都被排序好了
qq=[9,8,7,66,55,4,3,2,1]
print('原始排列是'+str(qq))
for i in range(len(qq)-1):
for j in range(i+1,len(qq)):
if qq[i]>qq[j]:
qq[i],qq[j]=qq[j],qq[i]
print('这次排序后变为:'+str(qq))
print('--------------------------------------------------')
print('最终排序结果是:'+str(qq))
我当时也在想改进版的选择排序,用了上面冒泡排序一样的flag标记法,后来一想不对啊!冒泡排序是从前到后每一个都比,所以只要某一轮的flag为0则说明数列是正确顺序排列的,但是选择排序的某一轮flag为0只能说明这个元素被放在了正确的位置,后面的元素不一定呀
(我过了一小时来看我上面这段话,发现我不知道自己在说啥了…就这样吧)
总结:选择排序是从前往后依次把正确的元素放在指定位置
3.插入排序
插入排序的思路是这样的,先排好前2个元素,再把第三个元素插到正确的位置,这样前三个元素都是正确排序的了,再把第四个元素插到正确的位置…这样重复下去直至所有元素都被插入到了正确的位置
具体这样:先比较前两个元素,很好操作,位置对了就保持原样,不对的对调位置
然后看第三个元素,先让它跟第二个比,如果比第二个大,不用再和第一个元素比了,因为前两个元素已经是排列好的了,比第二个都大了肯定也比第一个大,那么第三个元素就不用动;如果比第二个小,那就再和第一个比,比第一个大就把第三个元素放到一二元素之间,比第一个小就放在第一个元素前面
下面来看第k个元素,先和第k-1个比,一直推进。如果比谁小,就继续往前比,一直到遇到比自己小的,就把自己放在它后面,如果很不幸,比到头了都没遇到比自己小的,那就把自己放在第一个位置
qq=[9,8,7,66,55,4,3,2,1]
print('初始顺序是:'+str(qq))
for i in range(1,len(qq)):
tem=qq[i]
no=i-1
while no>=0 and tem<qq[no]:
qq[no+1]=qq[no]
no=no-1
qq[no+1]=tem
print('这次排序完的结果是:'+str(qq))
print('----------------------------------------------------------')
print('最终排序结果是:'+str(qq))
说的容易,插到谁后面,但是用python的数组的话就很麻烦,后面的每个数都得后移一个位置。用python的链表结构应该会方便点,下次可以试试
4.希尔排序
我把希尔排序看作是插入排序plus版,更加快捷的排序方式
插入排序的每个元素插入时,是逐个往前比的,但是希尔排序先给元素分组,再用插入排序比,不用逐个比,只要往前比固定间隔的元素即可。然后不断减小间隔,直到最终每个元素都是独立的个体
为了方便就先二分再四分再八分一直到分完吧…
data=[9,8,7,66,55,4,3,2]
print('原始顺序是:'+str(data))
s=len(data)
d=s//2
while d!=0:
for i in range(d,s):
te=data[i]
j=i-d
while j>=0 and te<data[j] :
data[j+d]=data[j]
j=j-d
data[j+d]=te
print('这次的排序结果是:'+str(data))
d=d//2
print('-------------------------------------------------')
print('最终的排序结果是:'+str(data))
5.快速排序
快排是最重要的一种排序方式,也是公认的最佳排序?思路是先随便找一个数,然后把小于它的放它左边,大于它的放它右边,再以同样的方式处理它左右的元素,一直到排序完成
看起来好像很容易,但是python实现真的好复杂啊,我感觉好难,看了好久才弄明白,而且我估摸着过几天我又看不懂了自己在写啥了
def quick(d,size,lf,rg):
#第一项键值为d[lf]
if lf<rg: #排序数列的左边与右边
lf_idx=lf+1
while d[lf_idx]<d[lf]:
if lf_idx+1 >size:
break
lf_idx +=1
rg_idx=rg
while d[rg_idx] >d[lf]:
rg_idx -=1
while lf_idx<rg_idx:
d[lf_idx],d[rg_idx]=d[rg_idx],d[lf_idx]
lf_idx +=1
while d[lf_idx]<d[lf]:
lf_idx +=1
rg_idx -=1
while d[rg_idx] >d[lf]:
rg_idx -=1
d[lf],d[rg_idx]=d[rg_idx],d[lf]
for i in range(size):
print('%3d' %d[i],end='')
print()
quick(d,size,lf,rg_idx-1) #以rg_idx为基准点分成左右两半以递归方式
quick(d,size,rg_idx+1,rg) #分别为左右两半进行排序直至完成排序