快速排序
def quickSort(arr,l,r):
if l >= r:
return
p = partition(arr,l,r)
quickSort(arr,l,p-1)
quickSort(arr,p+1,r)
def partition(arr,l,r): 把基准值移动到正确的排序位置
//首先以左边的值为基准值,固定其不动,游标i用来遍历整个数组,游标j来记录小于基准和 //大于基准值的分隔位置,j指向小于基准值的的最后一个位置,
//遍历的过程中如果当前值小于基准值就就交换当前值与大于基准值的第一个位置,即交换i与 //j+1的值,同时更新j的位置
//遍历完成后,将基准值和小于基准值的最后一个元素交换位置 即可完成函数任务
v = arr[l] # 选取基准值
j = l # 记录小于基准值位置的指针
for i in range(l+1,r+1):
if arr[i] <= v:
arr[i],arr[j+1] = arr[j+1],arr[i]
j+=1
arr[j],arr[l] = arr[l],arr[j]
return j
冒泡排序
思想:每次遍历完成后最大的在最后,所以叫做冒泡
def bullbeSort(arr,n):
for i in range(n-1):
count = 0
for j in range(n-1-i):
if arr[j]>arr[j+1]:
arr[j],arr[j+1] = arr[j+1],arr[j]
count+=1
if count ==0:
break
li = [4,2,5,6,2,1,342,35,123]
n = len(li)
bullbeSort(li,n)
print(li)
选择排序
思想:每次(外层遍历)找到最小的元素和第一个元素交换(内层遍历)位置
def selectSort(arr):
n = len(arr)
for i in range(n-1):
min_index = i
for j in range(i,n):
if arr[j]<arr[min_index]:
min_index = j
arr[i],arr[min_index] = arr[min_index],arr[i]
li =[12,23,45,2,4,2,5,324,532,12,532,412,4,314,2,6,4,7]
selectSort(li)
print(li)
归并排序
思想:将数组递归二分,分logN次成为两两有序的数组对,然后对有序的数组进行向上层合并
这里需要写一个将两个有序数组合并的程序
def mergeList(a,b):
i = 0
j = 0
c =[]
while i<len(a) and j<len(b):
if a[i]<b[j]:
c.append(a[i])
i+=1
else:
c.append(b[j])
j+=1
while j<len(b):
c.append(b[j])
j += 1
while i<len(a):
c.append(a[i])
i += 1
return c
def __mergeSort(arr,l,r):
new = []
if l>=r:
return
mid = (l+r)//2
__mergeSort(arr,l,mid)
__mergeSort(arr,mid+1,r)
//切记这里的下标 很容易出错
a = arr[l:mid+1]
b = arr[mid+1:r+1]
new = mergeList(a,b) //将新的合并好的数组放回原来数组的位置
for i in new:
arr[l] = i
l+=1
print(arr)
def mergeSort(arr):
l =0
r = len(arr)-1
__mergeSort(arr,l,r)
arr = [2,3,1,7,5,9,10,4,6,8]
mergeSort(arr)
计数排序
题目要求:数组只含0,1,2
思路:统计0 1 2的个数 然后进行创建新的数组
def sortColors(nums):
count = [0,0,0]
for num in nums:
assert num>=0 and num<=2,'数组元素在[0.2]之间'
count[num] += 1
print(count)
index = 0
for i in range(count[0]):
nums[index]=0
index+=1
for i in range(count[1]):
nums[index]=1
index+=1
for i in range(count[2]):
nums[index]=2
index+=1
print(nums)
nums = [1,2,2,1,2,1,0,0,1]
sortColors(nums)
双路快速排序
思想:目的是将数组分成左边全是小于v右边全部大于v,等于v的随机分布在两边,
采用两个指针一个从头开始遍历一个从尾部开始遍历,当左边遇到大于的就停止,右边遇到小于等于的也停止,然后交换他俩的位置 继续遍历,直到两个指针相遇(这句话是错误的,按照以上条件分析,i停在大于v的点,j停在小于v的点,故i和j不可能相遇,只可能穿过) 见代码实现
int __partition2(int arr[],int l,int r){
int v = arr[l];
//arr[l+1,,i]<=v,arr[j...r]>=v;
int i = l+1,j = r;
while(true){
while(i<=r && arr[i]<v)
i++;
while(j>=l+1 && arr[j]>v)
j--;
if(i>j)
break;
swap(arr[i],arr[j]);
i++;
j--;
}
swap(arr[l],arr[j]);
return j;
}
void __quickSort2(int arr[],int l,int r){
if (l>=r)
return;
int p = __partition2(arr,l,r);
__quickSort2(arr,l,p-1);
__quickSort2(arr,p+1,r);
}
void quickSort(int arr[],int n ){
__quickSort2(arr,0,n-1);
}
int main(){
int arr[5] = {1,3,2,7,4};
int n = 5;
cout << "Value of result is : " << endl;
quickSort(arr,n);
for(int s = 0;s<5;s++){
printf("%d",arr[s]);
}
return 0;
}
三路快速排序
思想:将数组划分为三部分,小于v,等于v,大于v,
#include <iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
void __quickSort3(int arr[],int l,int r){
if (l>r)
return;
//partition
//指针的初始值很重要
int v = arr[l];
int lt = l;//[l+1,lt]<v lt表示小于v的最后一个指针,当lt=时 集合为空满足定义
//当lt=l+1时集合为l+1,可能不满足定义,故这里要初始化为l
int gt = r+1;//gt表示大于v的第一个指针,同上这里初始化为r+1(即使这个指针不存在)
int i = l;//i作为遍历指针,同时也保持[lt+1...i)=v
while(i<gt){
if(arr[i]<v){
swap(arr[i],arr[lt+1]);
lt++;
i++;
}
else if(arr[i]>v){
swap(arr[i],arr[gt-1]);
gt--;
}else{
i++;
}
}
swap(arr[l],arr[lt]);
__quickSort3(arr,l,lt-1);
__quickSort3(arr,gt,r);
}
void quickSort3ways(int arr[],int n){
__quickSort3(arr,0,n-1);
}
int main(){
int arr[5] = {1,3,2,7,4};
int n = 5;
cout << "Value of result is : " << endl;
quickSort3ways(arr,n);
for(int s = 0;s<5;s++){
printf("%d",arr[s]);
}
cout<<"finially!"<<endl;
}