10.10 查找列表
)线性查找
线性查找顺序地将关键字key与列表中的每一个元素进行比较,直到找到某个匹配元素时返回其下标,亦或在找不到时返回-1。代码如下:
# The function for finding a key in a list
def linearSearch(lst, key):
for i in range(len(lst)):
if lst[i] == key:
return i
return -1
若关键字存在,线性查找在找到关键字前平均需要查找一半的元素,其运行时间与列表中的元素个数成正比(时间复杂度为O(n)?)。这样的效率十分低下。
)二分查找
在保证关键字是升序排序的基础上,使用二分查找效率很高。其核心在于若关键字比中间的元素大,则仅在中间元素右边寻找,即更新low = mid + 1;若关键字比中间元素小,则仅在中间元素左边寻找,所以更新high = mid - 1;若关键字与中间元素一样大,则找到结果mid。不断循环,若最后有high > mid,则表示找不到关键字元素,则返回-low-1标记关键字应当被放置的位置。代码如下:
# Use binary search to find key in the list
def binarySearch(lst, key):
low = 0
high = len(lst) - 1
while high >= low:
mid = (low + high) // 2
if key < lst[mid]:
high = mid - 1
elif key == lst[mid]:
return mid
else:
low = mid + 1
return -low - 1
此算法的时间复杂度为O(logn),比起线性查找高效很多,但前提是保证列表中的元素已经有序。
10.11 排序列表
)选择排序
选择排序的核心思想是,在每一次循环中找列表中最小元素与当前的第一个元素交换位置,然后再对剩余列表往复此操作,从而达到使列表中元素升序排列的目的。代码如下:
# The function for sorting elements in ascending order
def selectionSort(lst):
for i in range(len(lst)-1):
currentMin = lst[i]
currentMinIndex = i
for j in range(i + 1, len(lst)):
if lst[j] < currentMin:
currentMin = lst[j]
currentMinIndex = j
if currentMinIndex != i:
lst[currentMinIndex] = lst[i]
lst[i] = currentMin
选择排序的平均时间复杂度为O(n2)
) 插入排序
插入排序的核心思想是,在每一次循环中将一个新的元素插入到已经排好序的列表中,再对剩余元素往复此操作,从而达到使列表中元素升序排列的目的。代码如下:
# The function for sorting elements in ascending order
def insertionSort(lst):
for i in range(1, len(lst)):
currentElement = lst[i]
k = i - 1
while k >= 0 and lst[k] > currentElement:
lst[k+1] = lst[k]
k -= 1
lst[k+1] = currentElement
此算法的时间复杂度亦为O(n2),但其并不是每次都几乎遍历整个列表,因此在常数上会比选择排序略小。
排序的算法还有冒泡排序、快速排序、堆排序等等,这里仅举例实现。
10.12 实例学习:弹球
在屏幕上使一系列弹球运动,并通过按钮使增加一个弹球或减少一个弹球,弹球以列表的形式储存,代码如下:
from tkinter import *
from random import randint
def getRandomColor():
color = "#"
for j in range(6):
color += toHexChar(randint(0,15))
return color
def toHexChar(hexValue):
if 0 <= hexValue <= 9:
return chr(hexValue + ord('0'))
else:
return chr(hexValue + ord('A') - 10)
class Ball:
def __init__(self):
self.x = 0
self.y = 0
self.dx = 2
self.dy = 2
self.radius = 3
self.color = getRandomColor()
class BounceBalls:
def __init__(self):
self.ballList = []
window = Tk()
window.title("Bouncing Balls")
self.width = 350
self.height = 150
self.canvas = Canvas(window, bg = "white", width = self.width, height = self.height)
self.canvas.pack()
frame = Frame(window)
frame.pack()
btStop = Button(frame, text = "Stop", command = self.stop)
btStop.pack(side = LEFT)
btResume = Button(frame, text = "Resume", command = self.resume)
btResume.pack(side = LEFT)
btAdd = Button(frame, text = "+", command = self.add)
btAdd.pack(side = LEFT)
btRemove = Button(frame, text = "-", command = self.remove)
btRemove.pack(side = LEFT)
self.sleepTime = 100
self.isStopped = False
self.animate()
window.mainloop()
def stop(self):
self.isStopped = True
def resume(self):
self.isStopped = False
self.animate()
def add(self):
self.ballList.append(Ball())
def remove(self):
self.ballList.pop()
def animate(self):
while not self.isStopped:
self.canvas.after(self.sleepTime)
self.canvas.update()
self.canvas.delete("ball")
for ball in self.ballList:
self.redisplayBall(ball)
def redisplayBall(self, ball):
if ball.x > self.width or ball.x < 0:
ball.dx = -ball.dx
if ball.y > self.height or ball.y < 0:
ball.dy = -ball.dy
ball.x += ball.dx
ball.y += ball.dy
self.canvas.create_oval(ball.x-ball.radius, ball.y - ball.radius, ball.x + ball.radius, ball.y + ball.radius, fill = ball.color, tags = "ball")
BounceBalls()