1、冒泡排序
交换过程图示(第一次):
我们一共需要进行n-1次冒泡过程
def bubble_sort(list):
for i in range(len(list)-1,0,-1):
for j in range(i):
if(list[j]>list[j+1]):
list[j+1],list[j]=list[j],list[j+1]
range() 函数可创建一个整数列表,一般用在 for 循环中。 range(start, stop[, step])
参数说明:
- start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5);
- stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
- step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)
2、选择排序
它的工作原理如下:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
选择排序的主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素,它们当中至少有一个将被移到其最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换。
排序过程:
def selection_sort(l):
list = l.copy() #对于列表和字典,参数传递的方式是引用传递。对列表进行拷贝,这样不会改变参数l的值
n=len(list)
for i in range(n-1):
maxidx=i
for j in range(i+1,n):
if list[j]>list[maxidx]:
maxidx=j
if maxidx!=i:
list[i],list[maxidx]=list[maxidx],list[i]
return list
3、插入排序
插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前 扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
插入排序分析
def insert_sort(l):
list = l.copy()
# 从第二个位置,即下标为1的元素开始向前插入
for i in range(1,len(list)):
# 从第i个元素开始向前比较,如果小于前一个元素,交换位置
for j in range(i,0,-1):#不包含0
if list[j]<list[j-1]:
list[j],list[j-1]=list[j-1],list[j]
return list
希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法
希尔排序的基本思想是:将数组列在一个表中并对列分别进行插入排序,重复这过程,不过每次用更长的列(步长更长了,列数更少了)来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身还是使用数组进行排序。
def shell_sort(l):
list=l.copy()
gap=len(list)//2
while gap>0:
for i in range(gap,len(list)):
j=i;
while j>=gap and list[j]<list[j-gap]:
list[j - gap], list[j] = list[j], list[j - gap]
j=j-gap
gap=gap//2
return list
5、快速排序
快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为较小和较大的2个子序列,然后递归地排序两个子序列。步骤为:
- 挑选基准值:从数列中挑出一个元素,称为"基准"(pivot);
- 分割:重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(与基准值相等的数可以到任何一边)。在这个分割结束之后,对基准值的排序就已经完成;
- 递归排序子序列:递归地将小于基准值元素的子序列和大于基准值元素的子序列排序。
递归到最底部的判断条件是数列的大小是零或一,此时该数列显然已经有序。选取基准值有数种具体方法,此选取方法对排序的时间性能有决定性影响。
def partition(arr,low,high):
i = low-1 # 最小元素索引,正确
pivot = arr[high]
for j in range(low , high):
# 当前元素小于或等于 pivot
if arr[j] <= pivot:
i = i+1
arr[i],arr[j] = arr[j],arr[i]
arr[i+1],arr[high] = arr[high],arr[i+1]
return ( i+1 )
# 快速排序函数
def quickSort(arr,low,high):
if low < high:
pi = partition(arr,low,high)
quickSort(arr, low, pi-1)
quickSort(arr, pi+1, high)
arr = [10, 7, 8, 9, 1, 5]
n = len(arr)
quickSort(arr,0,n-1)
6、归并排序原理
归并排序采用分而治之的原理:
一、将一个序列从中间位置分成两个序列;
二、在将这两个子序列按照第一步继续二分下去;
三、直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。
def merge_sort( li ):
#不断递归调用自己一直到拆分成成单个元素的时候就返回这个元素,不再拆分了
if len(li) == 1:
return li
mid = len(li) // 2
#对拆分过后的左右再拆分 一直到只有一个元素为止,最后一次递归时候ll和lr都会接到一个元素的列表
ll = merge_sort( li[:mid] )
rl =merge_sort( li[mid:] )
# 对返回的两个拆分结果进行排序后合并再返回正确顺序的子列表
return merge(ll , rl)
def merge( left , right ):#left,right列表本身就是有序的
# 从两个有顺序的列表里边依次取数据比较后放入result,每次我们分别拿出两个列表中最小的数比较,把较小的放入result
result = []
while len(left)>0 and len(right)>0 :
#为了保持稳定性,当遇到相等的时候优先把左侧的数放进结果列表,因为left本来也是大数列中比较靠左的
if left[0] <= right[0]:
result.append( left.pop(0) )
else:
result.append( right.pop(0) )
#while循环出来之后 说明其中一个数组没有数据了,我们把另一个数组添加到结果数组后面
result += left
result += right
return result
if __name__ == '__main__':
li = [5,4 ,3 ,2 ,1]
li2 = merge_sort(li)
print(li2)
left.pop(index) 该方法返回从列表中移除的元素对象。
二分法查找
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表。折半查找方法适用于不经常变动而查找频繁的有序列表。
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
def binary_select(list,item):
first=0
last=len(list1)-1
while last>=first:
mid = first + last // 2
if list[mid]==item:
return mid
if list[mid]>item:
last=mid-1
if list[mid]<item:
first = mid+1
return False