网页设计色彩搭配seo服务收费
列表相关操作
- 第17节课 列表相关操作
- 1 常规操作
- 2 查找操作
- 3 排序操作
第17节课 列表相关操作
无论是内置函数、对象函数,用起来确实很方便,但是作为初学者,你必须懂得它们背后的运行逻辑!
1 常规操作
(1)遍历
arr = [1,2,3,4]
# 以索引遍历:可以在遍历期间修改元素
for index in range(len(arr)):arr[index] = arr[index] ** 2print(arr[index])
print(arr)# 以元素遍历:只能获取元素,不能修改元素值(可变对象除外)
for element in arr:print(element)# 同时遍历角标和元素
for index, element in enumerate(arr):print(f"角标{index},元素{element}")# 反向遍历
for index in range(len(arr) - 1, -1, -1):print(arr[index])
(2)最值
def min_max(arr:list[int]) -> tuple:min_value = arr[0]max_value = arr[0]for i in range(1, len(arr)):if arr[i] > max_value:max_value = arr[i]if arr[i] < min_value:min_value = arr[i]return min_value, max_valuearr = [2,9,8,1,7,4,6,3,5]
min_val, max_val = min_max(arr)
print(min_val, max_val)
(3)存在性
arr = [2,9,8,1,7,4,6,3,5]
#O(n)
def is_exist(arr:list[int], key:int) -> bool:for element in arr:if element == key:return Truereturn Falseprint(is_exist(arr, 10))
print(is_exist(arr, 8))
(4)反转
arr = [1,2,3,4,5,6,7,8,9]
"""
1 2 3 4 5 6 7 8 9lr
"""
def list_reverse(arr:list[int]) -> None:l = 0r = len(arr) - 1while l < r:arr[l], arr[r] = arr[r], arr[l]l += 1r -= 1list_reverse(arr)
print(arr)
(5)乱序
import random
arr = [1,2,3,4,5,6,7,8,9]def list_shuffle(arr):for i in range(len(arr)):j = random.randint(0, len(arr) - 1)arr[i], arr[j] = arr[j], arr[i]list_shuffle(arr)
print(arr)
(6)二维列表
所谓的二维列表,其实本质上就是一个一维列表,只不过该一维列表中的每一个元素为其他的一维列表
def print_matrix(matrix):for i in range(len(matrix)):for j in range(len(matrix[i])):print(matrix[i][j], end = ' ')print()
# 直接填值创建二维列表
matrix = [[1,2,3], [4,5,6], [7,8,9]]
print(len(matrix))
print(len(matrix[1]))
print_matrix(matrix)
matrix = [[1,2,3,4],[1,2,3],[1,2],[1]
]
print_matrix(matrix)# 循环创建二维列表 指定默认值 0
rows = 3
cols = 5
matrix = []
for i in range(rows):row = [0] * colsmatrix.append(row)
matrix[2][2] = 6
print_matrix(matrix)# 列表推导式创建二维列表
matrix = [[0] * cols for _ in range(rows)]
matrix[2][2] = 6
print_matrix(matrix)matrix = [ [i + j for j in range(cols)] for i in range(rows)]
print_matrix(matrix)
2 查找操作
(1)二分查找
前提数据必须是有序的(升序、降序)
# 返回的是元素key在arr中的角标 如果不存在则返回-1
def binary_search(arr, key): #O(log n)left = 0right = len(arr) - 1mid = (left + right) // 2while arr[mid] != key:if arr[mid] < key:left = mid + 1elif key < arr[mid]:right = mid - 1if left > right:return -1# 重新更新mid的值mid = (left + right) // 2return mid# 顺序查找
def linear_search(arr, key):for index in range(len(arr)):if arr[index] == key:return indexreturn -1# arr = [1,2,3,4,5,6,7,8,9]
# key = 6
# print(binary_search(arr, key))
"""
n/2/2/2/2/..../2 = 1
n/2^x = 1
n = 2^x
x = logn
"""
arr = []
for i in range(70000000):arr.append(i)
key = 69999999
print("数据创建完毕...")
print(binary_search(arr, key))
print(linear_search(arr, key))
(2)插值查找
前提数据必须是有序的(升序、降序),它是二分查找的升级版本
# mid = (key - arr[left]) / (arr[right] - arr[left]) * (right - left) + left
# 当数据分布比较均匀的时候 大致满足等差序列的情况 性能要比二分查找要优秀
def interpalotion_search(arr, key):count = 0left = 0right = len(arr) - 1mid = 0# mid = int((key - arr[left]) / (arr[right] - arr[left]) * (right - left)) + left# while arr[mid] != key:# count += 1# if arr[mid] < key:# left = mid + 1# elif key < arr[mid]:# right = mid - 1# if left > right:# mid = -1# break# mid = int((key - arr[left]) / (arr[right] - arr[left]) * (right - left)) + leftwhile True:count += 1mid = int((key - arr[left]) / (arr[right] - arr[left]) * (right - left)) + left# key本身在范围外 没找到if mid < left or mid > right:mid = -1breakif arr[mid] < key:left = mid + 1elif key < arr[mid]:right = mid - 1else:break# 在范围内没找到if left > right:mid = -1breakprint(f"插值查找count={count}")return middef binary_search(arr, key): #O(log n)count = 0left = 0right = len(arr) - 1mid = (left + right) // 2while arr[mid] != key:count += 1if arr[mid] < key:left = mid + 1elif key < arr[mid]:right = mid - 1if left > right:mid = -1break# 重新更新mid的值mid = (left + right) // 2print(f"二分查找count={count}")return mid
# int((20 - 1)/(20-1) * (19 - 0)) + 0 = 19
# int((100 - 1)/(20 - 1) * (19 - 0))+ 0 = 99
# int((-100 - 1)/(20 - 1)*(19-0)) + 0 = - 101
arr= [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
key = -100
print(binary_search(arr, key))
print(interpalotion_search(arr, key))
3 排序操作
希尔排序、堆排序、快速排序、归并排序、计数排序、基数排序、桶排序
(1)选择排序
# 选择排序 O(n^2)
"""
从前往后 每一个元素都要跟其后面的其他元素作比较
如果出现左大右小 则进行交换
"""
def selection_sort(arr):for i in range(len(arr) - 1): # 少一轮for j in range(i + 1, len(arr)):if arr[i] > arr[j]:arr[i], arr[j] = arr[j], arr[i]
arr = [5,2,3,1,4]
selection_sort(arr)
print(arr)
(2)冒泡排序
# 冒泡 O(n^2)
"""
从前往后 元素之间两两进行比较
如果左大右小则交换
"""
def bubble_sort(arr):# 0 1 2 3for i in range(len(arr) - 1): #-1 少一轮for j in range(len(arr) - i - 1):if arr[j] > arr[j + 1]:arr[j], arr[j + 1] = arr[j + 1], arr[j]arr = [5,2,3,1,4]
bubble_sort(arr)
print(arr)
(3)插入排序
# 选择 O(n^2)
def insertion_sort(arr):# 从第2个元素开始遍历for i in range(1, len(arr)):j = iwhile j > 0 and arr[j - 1] > arr[j]:arr[j - 1], arr[j] = arr[j], arr[j - 1]j -= 1
arr = [5,2,3,1,4]
insertion_sort(arr)
print(arr)
根据循环的特性来去解决特定的问题,而不是学习循环本身,学算法思想!
循环之间的好坏其实也有区别,主要在于数据的分布情况
(1)大致升序
(2)大致降序
(3)趋于稳定(方差小,相等值比较多)
(4)完全随机
用time模块记录一下运行时间