1. 概念
- 数据结构
计算机存储和组织数据的方式。通俗的讲,计算机按不同数据结构存储数据,决定着其保存数据的形式及将数据存入和取出的效率,不同数据结构,存储数据和读取数据占用的时间和空间不同。
- 算法
计算机完成一个任务的整个流程即为一种算法。概念上讲,算法和数据结构没有任何联系,但一般地,使用不同的数据结构实现同一功能往往效率不同,因此,算法与数据结构密不可分。
- 算法的五大特性
- 输入: 算法具有0个或多个输入;
- 输出: 算法至少有1个或多个输出;
- 有穷性: 算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤可以在可接受的时间内完成;
- 确定性:算法中的每一步都有确定的含义,不会出现二义性;
- 可行性:算法的每一步都是可行的,也就是说每一步都能够执行有限的次数完成;
- 时间复杂度
计算机实现某一算法所需的基本操作数。注意,时间复杂度并不是完成某一算法的耗时。所谓基本操作数,可以理解为计算机执行指令的最小单元,例如执行加法,减法,判断,等。通常采用大O表示法表示时间复杂度。
- 大O表示法
时间复杂度和大O表示法有专门的数学函数表达式解释,在此不作详解(看了又忘)。可以理解为,当要对数量为n的数据实现至某一规则时,所需最多操作数可以表示为与n相关的某个函数表达式的值。一般地,大O表示法只取决于表达式中次数最高项,次级次数项,常数项,系数等都忽略。
- 时间复杂度分类
- 最坏时间复杂度
- 最优时间复杂度
- 平均时间复杂度
- 时间复杂度计算规则
- 基本操作,即只有常数项,认为其时间复杂度为O(1);
- 顺序结构,时间复杂度按加法进行计算;
- 循环结构,时间复杂度按乘法进行计算;
- 分支结构,时间复杂度取最大值;
2. 算法初体验
了解了一些基本概念,接下来对算法的作用有个初步体验。
现假设现要计算如下问题:
求满足条件的所有a,b,c组合:a+b+c=1000, a^2 + b^2 =c^2。
- 方式一(直接上代码,逻辑比较简单):
import time
start_time = time.time()
for a in range(1001):
for b in range(1001):
for c in range(1002):
if a+b+c == 1000 and a*a+b*b == c*c:
print('a=%d,b=%d,c=%d' % (a, b, c))
end_time = time.time()
print('共耗时:%f' % (end_time-start_time))
- 结果
a=0,b=500,c=500
a=200,b=375,c=425
a=375,b=200,c=425
a=500,b=0,c=500
共耗时:123.326442
Process finished with exit code 0
- 方式二
import time
start_time = time.time()
for a in range(1001):
for b in range(1001):
c = 1000-a-b
if a*a+b*b == c*c:
print('a=%d,b=%d,c=%d' % (a, b, c))
end_time = time.time()
print('共耗时:%f' % (end_time - start_time))
- 结果
a=0,b=500,c=500
a=200,b=375,c=425
a=375,b=200,c=425
a=500,b=0,c=500
共耗时:0.281858
Process finished with exit code 0
可以看出,为实现同一目标,计算机使用不同算法结果相差多个数量级。
- 分析
根据上面时间复杂度计算规则,方式一时间复杂度为O(n^3), 而方式二时间复杂度为O(n^2)。因为此处n=1001,所以二者相差近3个数量级。
- 常见时间复杂度大小
O(1) < O(log n) < O(n) < O(nlog n) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
这里,log n 指以2为底,n的对数。
3. 常见数据结构
对算法有个初步的概念后,接下来了解下计算机中常见的数据结构。
- 顺序表:元素顺序地存放在一块连续的存储区里;
- 一体式顺序表:表头信息和内容相连;
- 分离式顺序表:表头信息和内容不相连;
python中list就是一种采用分离式技术实现的动态顺序表。
- 链表:元素存放在通过链接构造起来的一系列存储块中;
- 单向链表
- 单向循环链表:尾节点的下个节点指向头节点的单向链表;
- 双向链表:不仅上节点指向下节点,下节点同时指向上节点;
- 栈:一种先进后出的数据结构;
- 队列:一种先进先出的数据结构;
4. python实现常见数据结构
- pyhton实现单向链表
class Node(object):
"""节点"""
def __init__(self, item):
self.item = item
self.next = None # 指向下一节点
class SingleLinkList(object):
"""单向链表"""
def __init__(self):
self.__head = None # 头节点
def is_empty(self):
"""链表是否为空"""
return self.__head is None
def length(self):
"""链表长度"""
cur = self.__head
count = 0
while cur is not None:
cur = cur.next
count += 1
return count
def travel(self):
"""遍历链表"""
cur = self.__head # 创建游标指向头节点
while cur is not None:
print(cur.item, end=' ')
cur = cur.next
print() # 换行
def add(self, item):
"""链表头部添加节点"""
node = Node(item) # 创建节点
node.next = self.__head # 新节点下个元素指向头节点
self.__head = node # 头节点指向新节点
def append(self, item):
node = Node(item)
if self.is_empty():
self.__head = node
else:
cur = self.__head
while cur.next is not None:
cur = cur.next
cur.next = node
def insert(self, pos, item):
"""指定位置添加元素"""
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
node = Node(item)
cur = self.__head
index = 0
while index < pos-1: # 注意这里是pos-1
index += 1
cur = cur.next
node.next = cur.next
cur.next = node
def remove(self, item):
"""删除节点"""
cur = self.__head # 头节点
pre = None # 前一个节点
while cur is not None:
if cur.item == item:
if pre is None: # 首节点
self.__head = cur.next
else: # 中间节点(或尾节点)
pre.next = cur.next
break
# 链表继续后移
pre = cur
cur = cur.next
def search(self, item):
cur = self.__head
while cur is not None:
if cur.item == item:
return True
cur = cur.next
return False
- python实现单向循环列表
class Node(object):
"""单向链表节点"""
def __init__(self, item):
self.item = item
self.next = None
class SinCycLinkList(object):
"""单向循环链表"""
def __init__(self):
self.__head = None
def is_empty(self):
return self.__head is None
def length(self):
if self.is_empty():
return 0
cur = self.__head
count = 1
while cur.next != self.__head:
count += 1
cur = cur.next
return count
def travel(self):
cur = self.__head
if self.is_empty():
return
while cur.next != self.__head:
print(cur.item, end=' ')
cur = cur.next
print(cur.item)
def add(self, item):
node = Node(item)
cur = self.__head
if self.is_empty():
self.__head = node
node.next = node
return
while cur.next != self.__head:
cur = cur.next
node.next = self.__head
self.__head = node
cur.next = node
def append(self, item):
node = Node(item)
if self.is_empty():
self.add(item)
return
cur = self.__head
while cur.next != self.__head:
cur = cur.next
node.next = self.__head
cur.next = node
def insert(self, pos, item):
if pos <= 0:
self.add(item)
elif pos > self.length() - 1:
self.append(item)
else:
node = Node(item)
cur = self.__head
index = 0
while index < pos-1:
cur = cur.next
index += 1
node.next = cur.next
cur.next = node
def remove(self, item):
if self.is_empty():
return
cur = self.__head
pre = None
# 要删除的是头节点的话需要知道尾节点,因此先判断是头节点的情况
if cur.item == item:
while cur.next != self.__head:
pre = cur
cur = cur.next
# 循环执行完后,cur为尾节点
if pre is None: # 只有头节点
self.__head = None
else:
cur.next = self.__head.next
self.__head = self.__head.next
else:
while cur.next != self.__head:
if cur.item == item:
pre.next = cur.next
return
else:
pre = cur
cur = cur.next
if cur.item == item:
pre.next = self.__head
def search(self, item):
if self.is_empty():
return False
cur = self.__head
while cur.next != self.__head:
if cur.item == item:
return True
cur = cur.next
if cur.item == item:
return True
return False
- python实现双向链表
class DNode(object):
"""双向链表节点"""
def __init__(self, item):
self.item = item
self.pre = None
self.next = None
class DoubleLinkList(object):
"""双向链表"""
def __init__(self):
self.__head = None
def is_empty(self):
return self.__head is None
def length(self):
cur = self.__head
count = 0
while cur is not None:
cur = cur.next
count += 1
return count
def travel(self):
cur = self.__head
while cur is not None:
print(cur.item, end=' ')
cur = cur.next
print()
def add(self, item):
node = DNode(item)
if self.is_empty():
self.__head = node
else:
node.next = self.__head
self.__head.pre = node
self.__head = node
def append(self, item):
if self.is_empty():
self.append(item)
else:
cur = self.__head
while cur.next is not None:
cur = cur.next
node = DNode(item)
node.pre = cur
cur.next = node
def insert(self, pos, item):
if pos <= 0:
self.add(item)
elif pos > self.length()-1:
self.append(item)
else:
cur = self.__head
index = 0
while index < pos-1:
cur = cur.next
index += 1
node = DNode(item)
node.next = cur.next
node.pre = cur
cur.next.pre = node
cur.next = node
def remove(self, item):
cur = self.__head
while cur is not None:
if cur.item == item:
if cur.pre is None: # 头节点
self.__head = cur.next
else:
cur.pre.next = cur.next
if cur.next is not None:
cur.next.pre = cur.pre
return
cur = cur.next
def search(self, item):
cur = self.__head
while cur is not None:
if cur.item == item:
return True
cur = cur.next
return False
- python实现栈
class Stack(object):
"""栈"""
def __init__(self):
"""创建一个新的空栈"""
self.__list = list() # 栈底层使用list来实现
def is_empty(self):
"""判空"""
return self.__list == []
def size(self):
"""返回栈中元素个数"""
return len(self.__list)
def push(self, item):
"""添加一个新的元素item到栈顶"""
self.__list.append(item)
def pop(self):
"""弹出栈顶元素"""
if self.is_empty():
return None
return self.__list.pop()
def peek(self):
"""返回栈顶元素"""
if self.is_empty():
return None
return self.__list[self.size()-1]
- python实现队列
class Queue(object):
"""队列"""
def __init__(self):
self.__list = list() # 使用list实现队列
def is_empty(self):
return self.__list == []
def size(self):
return len(self.__list)
def enqueue(self, item):
"""往队列中添加一个元素"""
self.__list.append(item)
def dequeue(self):
"""从队列头中取出元素"""
if self.is_empty():
return None
return self.__list.pop(0)
添加和获取元素也可以分别使用
list.insert(0, item)
和list.pop()
实现。因此实现队列时,考虑是插入多还是删除多来选择使用不同的方法(实际上这里取出次数<=添加次数)。
5. 常见排序算法
介绍常见排序算法前介绍一个概念:排序算法的稳定性。指根据算法排序后,原本相等的两个元素的先后位置是否改变,改变则称不稳定。作为了解即可,实际使用中用到稳定性的情况并不多。
- 冒泡排序:相邻元素两两对比,将值大(小)的元素位置后移;
- 选择排序:特定位置的元素与其他元素对比,确保该位置元素最大(小);
- 插入排序:列表分为两部分,前者为已有序列表,将后者无序元素挨个和前者中元素比较,放置对应位置;
- 快速排序:找一个基准元素,将所有小于基准元素的放置一侧,大于(等于)基准元素的放置另一侧,递归,直至列表大小为0或者1,即肯定有序;
- 希尔排序:插入排序的改进版,先按一定间隔分组,每组插入排序,然后缩小间隔继续,直至间隔大小为1;
- 归并排序:将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位,然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来;
6. python实现常见排序算法
实现排序一般需要2-3层循环,对每层循环的作用应有清晰的逻辑,否则容易晕导致出错。可以先根据算法核心思想算出外层逻辑需要几次循环直接定义出,然后再定义内部每次循环的逻辑。
- python实现冒泡排序
def bubble_sort(alist):
# 因为冒泡排序每次将最大的数移动到最后,因此需要n-1次循环即可,因为其他排好后,第一个即是最小元素
for i in range(len(alist)-1): # n-1次循环
# 每次循环旨在将前n-i个元素中的最大元素放置至最后
# 由于是两两相邻比较,即拿到一个元素与该元素后元素比较,因此循环至n-i-1即可
for j in range(len(alist)-i-1):
# 核心思想为:将大的数向后移动
if alist[j] > alist[j+1]:
alist[j], alist[j+1] = alist[j+1], alist[j]
- 稳定性:稳定;
- 最坏时间复杂度:O(n^2);
- 最优时间复杂度:O(n),表示遍历一次后发现没有需要交换的元素。当然,为实现次功能需要额外加判断条件及时退出循环,如下:
def bubble_sort(alist):
# 因为冒泡排序每次将最大的数移动到最后,因此需要n-1次循环即可,因为其他排好后,第一个即是最小元素
for i in range(len(alist) - 1): # n-1次循环
# 每次循环旨在将前n-i个元素中的最大元素放置至最后
# 由于是两两相邻比较,即拿到一个元素与该元素后元素比较,因此循环至n-i-1即可
count = 0 # 定义一个计数器,当前后元素发生位置变化时加1,如果最后计数器为0,说明本身就是正序的
for j in range(len(alist) - i - 1):
# 核心思想为:将大的数向后移动
if alist[j] > alist[j + 1]:
alist[j], alist[j + 1] = alist[j + 1], alist[j]
count += 1
if count == 0:
break
- python实现选择排序
def select_sort(alist):
# 第一次将首位置换成最小值,以此类推,共需要n-1次
for i in range(len(alist)-1):
# 拿到第i个元素,与其之后的元素挨个比较,把较小值放置i位
for j in range(i+1, len(alist)):
if alist[i] > alist[j]:
alist[i], alist[j] = alist[j], alist[I]
稳定性:不稳定,从后往前放置时,先满足条件的元素先被放置最后,会与相等的元素改变先后位置;
最坏时间复杂度:O(n^2);
最优时间复杂度:O(n^2):需要从首个位置排到最后个位置;
- python实现插入排序
def insert_sort(alist):
# 首次分为第一个元素和其余元素两部分,从第二个元素开始,与前面元素挨个比较,直到找到属于自己的位置。因此外层需要n-1次
for i in range(len(alist)-1):
# 将i+1位置的元素,向前挨个比较,找到自己的位置。即由第i个元素依次向前直至第0个元素
for j in range(i+1, 0, -1):
if alist[j] < alist[j-1]:
alist[j], alist[j-1] = alist[j-1], alist[j]
稳定性:稳定;
最坏时间复杂度:O(n^2);
最优时间复杂度:O(n)。
- python实现快速排序
"""
快速排序和前面三种思想上有较大不同,不再是外层循环次数下,内层循环实现将某一元素放至某位置。其核心思想是以某个值作为基准值,
将小于该值的元素放至左侧(交换位置),大于该值的元素放至右侧(交换位置),然后分别将左右两侧列表递归再次排序。
"""
# 为了实现递归而不用重新定义左右列表变量,将左右下标作为参数
def quick_sort(alist, left, right):
# 1. 递归退出条件
if left >= right:
return
# 2. 核心:
# 以首值为基准值,判断元素大小交换位置
mid_value = alist[0]
while left < right:
# 循环找出小于基准值的元素放至左侧
while left < right and alist[right] >= mid_value:
right -= 1
alist[left] = alist[right]
# 循环找出大于基准值的元素放至右侧
while left < right and alist[left] < mid_value:
left += 1
alist[right] = alist[left]
# 循环结束后,left=right,该位置放基准值
alist[left] = mid_value
# 对基准值左右两侧元素递归快排
quick_sort(alist, 0, left-1)
quick_sort(alist, left+1, right)
稳定性:不稳定,后前交互比较大小替换位置,必然不稳定;
最坏时间复杂度:O(n^2),最大需要递归n-1次,每次中,内层循环最大都要比较n次;
最优时间复杂度:O(nlogn),每次几乎分一半一半时,需要logn次循环;
PS:快速排序较前面三种排序难度提升,但很重要。
- python实现希尔排序
"""
希尔排序是插入排序的改进版,先以一定步长将列表分为多个子列表,然后对每个子列表插入排序。执行完成后,缩小步长继续,直至步长为0。
这里可能会有疑惑,最终步长为1时就是插入排序,为什么还要多几次步长不为1的循环?
实际上,前面知道插入排序后面每个元素向前插入时,需要从前往后遍历比较,但如果比首个元素都小则可直接插入。我们可以理解为,对大部分
无序随机数列,步长取合适时,时间复杂度会有很大改善。
"""
def shell_sort(alist):
# 取首次步长为列表长度一半
gap = len(alist) // 2
while gap > 0:
# 内层类似插入排序,只不过步长为gap
# 循环次数:gap->len
for i in range(gap, len(alist)):
# 内层:将第i个元素依次与前面元素比较调整位置,不过步长为gap
for j in range(i, 0, -gap):
if alist[j] < alist[j-gap]:
alist[j], alist[j-gap] = alist[j-gap], alist[j]
# 排序后gap减小
gap = gap // 2
稳定:不稳定;
最坏时间复杂度:O(n^2);
最优时间复杂度:(数学统计最优可达O(n^1.3))
- python实现归并排序
"""
归并排序,如名字一样,是将序列一边合并一边排序。其核心思想为:
先将序列递归的折半拆分,直到长度为1,然后执行排序后作为本层递归的返回。
需注意归并排序每层递归都有返回值,因此比前面几个排序耗费空间。
"""
def merge_sort(alist):
# 1. 递归退出条件
if len(alist) <= 1:
return alist # 注意有返回值
# 2.核心思想
# 二分分解
num = len(alist) // 2
# 取左右两截(内部递归)
left_list = merge_sort(alist[0:num])
right_list = merge_sort(alist[num:])
# 返回根据左右两截实现的排序序列
return merge(left_list, right_list)
def merge(left_list, right_list):
# 排序核心:将左右两个有序数列内依次取满足大小比较的元素,放置新序列
# 定义左右两序列的其实元素位置
left, right = 0, 0
# 定义一个新序列接收排序后序列
result = list()
# 循环退出条件:一侧遍历完,将另一侧剩余元素直接添加至后面
while left < len(left_list) and right < len(right_list):
if left_list[left] < right_list[right]:
result.append(left_list[left])
left += 1
else:
result.append(right_list[right])
right += 1
result += left_list[left:]
result += right_list[right:]
return result
稳定性:稳定;
最坏时间复杂度:O(nlogn);
最优时间复杂度:O(nlogn);
- 常见排序算法效率比较
排序方法 | 平均时间复杂度 | 最优时间复杂度 | 最坏时间复杂度 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 |
选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 不稳定 |
插入排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 |
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(logn)-O(n) | 不稳定 |
希尔排序 | O(nlogn)-O(n^2) | O(n^1.3) | O(n^2) | O(1) | 不稳定 |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
7. 常见搜索算法
常见算法除排序算法外还有就是搜索算法了。常见的搜索算法有针对有序序列的二分查找法,和针对二叉树的广度优先和深度优先算法。
树是另一种抽象的数据结构,主要有根节点和子节点等概念。一般主要使用的就是二叉树,即每个节点最多只有两个子节点的树。对树概念比较陌生的读者可以自行百度一波,树数据结构的使用可以参考下图来理解,另外xml,html等都是树结构。
另外,对二叉树或完全二叉树和满二叉树(概念自行百度)有一些数学性质,如需了解可自行学习。
- python实现二分查找
"""
二分查找法核心思想为:
找中间值将序列(等分地)分成两段,判断要找的元素比中间值大还是小,小的话在左侧段继续二分查找,大的在右侧。
python实现二分查找可以通过递归和非递归两种方式实现
"""
def binary_search(alist, item):
"""非递归实现二分查找"""
# 定义出始末下标
start = 0
end = len(alist)-1
# 循环结束条件:二分查找的序列长度为大于0
while start <= end:
# 找到中间值下标
mid_point = (start+end) // 2
if item == alist[mid_point]:
return True
elif item > alist[mid_point]:
start = mid_point+1
else:
end = mid_point-1
return False
def binary_search(alist, item):
"""递归实现二分查找"""
# 递归结束条件:二分到长度为0时说明未找到
if len(alist) == 0:
return False
mid_point = len(alist) // 2
if alist[mid_point] == item:
return True
if alist[mid_point] > item:
return binary_search(alist[:mid_point], item)
else:
return binary_search(alist[mid_point+1:], item)
最坏时间复杂度:O(logn);
最优时间复杂度:O(1);
- python表示二叉树节点及实现树的创建
class Node(object):
"""二叉树节点"""
# 二叉树节点三个属性:值,左子节点,右子节点
def __init__(self, item):
self.item = item
self.lchild = None
self.rchild = None
class Tree(object):
"""(满)二叉树"""
# 二叉树初始化时需要根节点
def __init__(self):
self.__root = None
def add(self, item):
"""添加元素"""
node = Node(item)
if self.__root is None:
self.__root = node
else:
# 核心思想:将头节点加入至队列,先判断左节点,为空则将节点放置左侧;若不为空,判断右节点,为空则放置右节点。若左右都不为空,分别将左右
# 节点加入至队列尾,再取队列首节点继续上面逻辑
queue = list()
queue.append(self.__root)
while queue:
cur = queue.pop()
if cur.lchild is None:
cur.lchild = node
return
if cur.rchild is None:
cur.rchild = node
return
# 左右都不为空,将左右节点放置队列尾
queue.append(cur.rchild)
queue.append(cur.rchild)
- python实现二叉树深度优先遍历
"""
二叉树深度优先遍历根据遍历顺序不同可分为三类:
先序遍历:先访问根节点,再访问左节点,最后右节点;
中序遍历:先访问左节点,再访问根节点,最优右节点;
后续遍历:先访问左节点,再当问右节点,最后根节点,注意左节点永远在右节点前,后续指根节点和右节点的顺序。
"""
def preorder(root):
"""递归实现先序遍历"""
if root is None:
return
print(root.item)
preorder(root.lchild)
preorder(root.rchild)
def inorder(root):
"""递归实现中序遍历"""
if root is None:
return
inorder(root.lchild)
print(root.item)
inorder(root.rchild)
def postorder(root):
"""递归实现后续遍历"""
if root is None:
return
postorder(root.lchild)
postorder(root.rchild)
print(root.item)
- python实现二叉树广度优先遍历
"""
广度优先遍历的核心:从根节点开始,从上到下,从左到右遍历整个树的节点
"""
def breadth_travel(root):
if root is None:
return
queue = list()
queue.append(root)
while queue:
node = queue.pop(0)
print(node.item)
if node.lchild is not None:
queue.append(node.lchild)
if node.rchild is not None:
queue.append(node.rchild)
- 整合上述方法
class Node(object):
"""二叉树节点"""
# 二叉树节点三个属性:值,左子节点,右子节点
def __init__(self, item):
self.item = item
self.lchild = None
self.rchild = None
class Tree(object):
"""(满)二叉树"""
# 二叉树初始化时需要根节点
def __init__(self):
self.root = None
def add(self, item):
"""添加元素"""
node = Node(item)
if self.root is None:
self.root = node
else:
# 核心思想:将头节点加入至队列,先判断左节点,为空则将节点放置左侧;若不为空,判断右节点,为空则放置右节点。若左右都不为空,分别将左右
# 节点加入至队列尾,再取队列首节点继续上面逻辑
queue = list()
queue.append(self.root)
while queue:
cur = queue.pop(0) # 注意是取第0个元素,与下面的append相斥
if cur.lchild is None:
cur.lchild = node
return
if cur.rchild is None:
cur.rchild = node
return
# 左右都不为空,将左右节点放置队列尾
queue.append(cur.lchild)
queue.append(cur.rchild)
def preorder(self, root):
"""递归实现先序遍历"""
if root is None:
return
print(root.item)
self.preorder(root.lchild)
self.preorder(root.rchild)
def inorder(self, root):
"""递归实现中序遍历"""
if root is None:
return
self.inorder(root.lchild)
print(root.item)
self.inorder(root.rchild)
def postorder(self, root):
"""递归实现后续遍历"""
if root is None:
return
self.postorder(root.lchild)
self.postorder(root.rchild)
print(root.item)
def breadth_travel(self, root):
"""广度优先遍历"""
if root is None:
return
queue = list()
queue.append(root)
while queue:
node = queue.pop(0)
print(node.item)
if node.lchild is not None:
queue.append(node.lchild)
if node.rchild is not None:
queue.append(node.rchild)
深度优先一般用递归,广度优先一般用队列。一般情况下能用递归实现的算法大部分也能用堆栈来实现。
8. 结语
算法在编程语言中至关重要,但真正掌握好算法并不是一时半会儿能搞定的。理解掌握常用算法能对以后的积累和解决问题提供一定基础和思路。
上述算法比较简单,但掌握起来也并不容易。不需要记住每个的具体步骤,而且实现方式也不是唯一,但需要细心理解每个算法的核心思想,多写几次,才能达到比较熟练的水平。