目录
排序学习python
二叉搜素
def binarySearch(target,sortedList):
"""二分查找有序数组中目标值"""
left = 0
right = len(sortedList) - 1
while left <= right:
midPoint = (left + right) // 2
if target == sortedList[midPoint]:
return midPoint
elif target < sortedList[midPoint]:
right = midPoint - 1
else:
left = midPoint + 1
return -1
binarySearch(44 ,[1,3,4,7,20,33,34,44,55,66,77])
选择排序selectSort
# 第一步:遍历每一个位置,认为每个位置即为从此位置往后中最小的值
# 第二步:在第一步的位置以后去找最小值位置
# 第三步:第一步位置与最小值位置比较,不一样就交换
# 时间复杂度:O(n^2)
# For循环:
def selectSort(s):
for i in range(len(s)):
minPoint = i
for j in range(i+1,len(s)):
if s[j] < s[minPoint]:
minPoint = j
if i != minPoint:
s[i], s[minPoint] = s[minPoint], s[i]
return s
冒泡排序bubbleSort
思想:每次遍历前后比较会把最大的数交换到最后面的位置
I:就是每次循环来控制范围的
J:在i控制的范围内做交换
时间复杂度:O(n^2)
基础版:(复杂度固定用for)
#For循环:
#(1)
def bubbleSort(s):
for i in range(len(s)-1):
for j in range(len(s)-1-i):
if s[j] > s[j+1]:
s[j], s[j+1] = s[j+1], s[j]
return s
lis = [85, 28 , 53, 72, 14, 11, 31, 52, 69, 17, 75, 12, 31, 41, 83 ]
bubbleSort(lis)
#(2)
def bubbleSort(s):
for i in range(len(s)-1,0,-1):
for j in range(i):
if s[j] > s[j+1]:
s[j], s[j+1] = s[j+1], s[j]
return s
lis = [85, 28 , 53, 72, 14, 11, 31, 52, 69, 17, 75, 12, 31, 41, 83 ]
bubbleSort(lis)
#while循环:
#(1)
def bubbleSort(s):
i = 0
while i < len(s)-1:
j = 0
while j < len(s)-i-1:
if s[j] > s[j+1]:
s[j], s[j+1] = s[j+1], s[j]
j += 1
i += 1
return s
lis = [85, 28 , 53, 72, 14, 11, 31, 52, 69, 17, 75, 12, 31, 41, 83 ]
bubbleSort(lis)
#(2)
def bubbleSort(s):
i = len(s) - 2
while i > 0:
j = 0
while j < i:
if s[j]>s[j+1]:
s[j],s[j+1] = s[j+1],s[j]
j += 1
i -= 1
return s
lis = [85, 28 , 53, 72, 14, 11, 31, 52, 69, 17, 75, 12, 31, 41, 83 ]
bubbleSort(lis)
改良版:(标志是否交换,有最好情况)
def bubbleSort(s):
for i in range(len(s)-1):
ischange = 0#标志是否要交换,初始为不交换
for j in range(len(s)-1-i):
if s[j]>s[j+1]:
s[j],s[j+1]=s[j+1],s[j]
#print(ischange)
ischange = 1#交换操作后置1
if not ischange :#如果没有交换说明已经排序好了
print(i,j,ischange)
return s
return s
java版本
import java.util.Arrays;
public class Test1 {
public static int[] bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean flag = true;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
flag = false;
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (flag) {
break;
}
}
return arr;
}
public static void main(String[] args) {
int[] res = { 85, 28, 53, 72, 14, 11, 31, 52, 69, 17, 75, 12, 31, 41, 83 };
int[] r = bubbleSort(res);
System.out.println(Arrays.toString(r));
}
}
应用
leetcode:力扣
插入排序insertSort
插入排序的主要思想是每次取一个列表元素与列表中已经排序好的列表段进行比较,然后插入从而得到新的排序好的列表段,最终获得排序好的列表。
比如,待排序列表为[49,38,65,97,76,13,27,49],则比较的步骤和得到的新列表如下:
(带有背景颜色的列表段是已经排序好的,红色背景标记的是执行插入并且进行过交换的元素)
def insertSort(s):
for i in range(1,len(s)):
itemToInsert = s[i]
j = i -1
while j >= 0:
if itemToInsert < s[j]:
s [j+1] = s[j]
j -= 1
else:
break
s[j+1] = itemToInsert
return s
lis = [85, 28 , 53, 72, 14, 11, 31, 52, 69, 17, 75, 12, 31, 41, 83 ]
insertSort(lis)
快速排序quickSort
思想:给一个元素找到他最终的位置,比他大的放右边,比他小的放左边
def quick_sort(param, start, end):
if start > end:
return param
mid = param[end]
left, right = start, end
while left < right:
# mid存储了end, 可以覆盖,所以这里先移动start对应的left(反过来mid=param[start],那就先处理right)
while left < right and param[left] <= mid:
left += 1
param[right] = param[left] # 找到左边第一个比mid标杆大的数,扔到右边
while left < right and param[right] > mid:
right -= 1
param[left] = param[right] # 找到右边第一个比mid标杆小的数,扔到左边
param[right] = mid # 标杆的最后位置找到了---right的现在的位置
quick_sort(param, start + 1, end)
quick_sort(param, start, end - 1) # 保证右边扔到左边的数很大没有找到自己的位置
return param
s = [85, 28 , 53, 72, 14, 11, 31, 52, 69, 17, 75, 12, 31, 41, 83 ]
quick_sort(s,0,len(s)-1)
java版本
import java.util.Arrays;
public class Test1 {
// 快排
public static int[] quickSort(int[] arr, int start, int end){
if (start > end) {
return arr;
}
int left = start;
int right = end;
int temp = arr[start];
while (left < right) {
while(left<right && arr[right]>temp){
right--;
}
arr[left] = arr[right];
while(left<right && arr[left]<=temp){
left++;
}
arr[right]=arr[left];
}
arr[left]=temp;
quickSort(arr, start+1, end);
quickSort(arr, start, end-1);
return arr;
}
public static void main(String[] args) {
int[] res = { 85, 28, 53, 72, 14, 11, 31, 52, 69, 17, 75, 12, 31, 41, 83 };
int[] r = quickSort(res,0,res.length-1);
System.out.println(Arrays.toString(r));
}
}
应用:
(1)leetcode:力扣
def smallestK(self, arr: List[int], k: int) -> List[int]:
if k >= len(arr):
return arr
if k == 0:
return []
def _quick_sort_k(nums, k, start, end):
flag = nums[start]
left, right = start, end
while left < right:
while left < right and nums[right] >= flag:
right -= 1
nums[left] = nums[right]
while left < right and nums[left] < flag:
left += 1
nums[right] = nums[left]
nums[left] = flag
if left == k - 1: # 找到了
return arr[: left+1]
elif left < k - 1:
return _quick_sort_k(nums, k, left+1, end)
else:
return _quick_sort_k(nums, k, start, left-1)
return _quick_sort_k(arr, k, 0, len(arr)-1)
java版本
class Solution {
public static void quickSort(int[] arr, int k, int start, int end){
int temp = arr[start];
int left = start;
int right = end;
while(left < right){
while(left<right && arr[right]>temp){
right--;
}
arr[left]=arr[right];
while(left<right && arr[left]<=temp){
left++;
}
arr[right]=arr[left];
}
arr[left] = temp;
if(left == k-1){
// 找到了位置
return;
}else{
if(left < k-1){
//说明还没有找够
quickSort(arr, k, left+1, end);
}else{
//说明找的多了
quickSort(arr, k, start, left-1);
}
}
}
public int[] smallestK(int[] arr, int k) {
if(k>arr.length){
return arr;
}
if(k==0){
return new int[] {};
}
quickSort(arr,k,0,arr.length-1);
int[] b = Arrays.copyOfRange(arr, 0, k);//存放返回元素
return b;
}
}
(2)面试题:输出第k大的正整数,如果第K大正整数不存在,返回-1
这里我觉得需要规定输入的list都是由正整数组成,或者求第k大的数,因为题目下面的补充是这个意思
def search_k(nums, k):
def _quick_sort(nums, k, start, end):
# if start > end: #找到最后的情况,这里应该走不到
# return -1
flag = nums[start]
left, right = start, end
while left < right:
while left < right and nums[right] <= flag:
right -= 1
nums[left] = nums[right]
while left < right and nums[left] > flag:
left += 1
nums[right] = nums[left]
nums[left] = flag
if left == k - 1: # left这个位置是这个flag的数的最终位置,左边是比他大的,右边比他小
# 如果left的位置就是k-1,那就是第k大数了
return nums[left]
elif left < k - 1:
return _quick_sort(nums, k, left + 1, end)
else:
return _quick_sort(nums, k, start, left - 1)
if len(nums) < k: #第k大的数不存在
return -1
return _quick_sort(nums, k, 0, len(nums) - 1)
if __name__ == '__main__':
nums = [4, 2, 1, 3, 5, 6, 5, 6]
print(search_k(nums, 5))
归并排序mergeSort
归并排序采用分而治之的原理:
一、将一个序列从中间位置分成两个序列;
二、在将这两个子序列按照第一步继续二分下去;
三、直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。
时间复杂度: 最好最坏都是 O( n log n )
稳定性:稳定
缺点:每次拆分数组都要开辟新的数组, 每次合并数组都要开新数组,空间复杂度很大
# (1)排序一个list
def merge(left, right):
res = []
while left and right:
if left[0] <= right[0]:
res.append(left.pop(0))
else:
res.append(right.pop(0))
res += left
res += right
return res
def merge_sort(param):
if len(param) <= 1:
return param
mid = len(param) // 2
left, right = param[:mid], param[mid:]
res_left = merge_sort(left)
res_right = merge_sort(right)
return merge(res_left, res_right)
(2)链表中的归并排序
class Node():
'''定义一个链表类'''
def __init__(self,val,next =None):
self.val = val
self.next = next
#构造测试数据
head = None
for i in range(1,6):
head = Node(i,head)
#验证新建数据
res = head
while res:
print(res.val)
res = res.next
#链表排序
def sortList( head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None or head.next is None:
return head
pre = head
slow = head
quick = head
while quick and quick.next:
pre = slow
slow = slow.next
quick = quick.next.next
left = head
right = pre.next
pre.next = None
left = sortList(left)
right = sortList(right)
return merge(left,right)
#归并排序
def merge(left,right):
res = Node(0)
result = res
while left and right:
if left.val < right.val:
res.next = left
left = left.next
else:
res.next = right
right = right.next
res = res.next
if left:
res.next = left
if right:
res.next = right
return result.next
#调用函数
t = sortList( head)