用Python学习算法与数据结构__1


用Python学习算法与数据结构

本文将《我的第一本算法书》中的一些概念记录下来,并使用python对其中的算法进行实现,作为本人学习python和算法的一个记录。详细算法说明参考《我的第一本算法书》中对应章节。

1.数据结构

数据结构的类型:

  • 链表:数据线性排列,每个数据都有指向链表下一个数据的指针,访问时需要从头开始读取,添加时只需要从所需位置添加数据,让上一个指向它并且它的指针指向下一个数据即可,删除也类似,被删除的数据空间将被闲置,再次使用时用新数据覆盖即可。
  • 数组:数据线性排列,可以根据下标直接对数组中存储的数据进行访问,但是在指定位置添加或删除数据时需要对数组中的数据进行移动,较为复杂。
  • 栈:数据线性排列,像是一个容器一般,先进入的数据最后出(FILO,First In Last Out)。添加的操作称为入栈(Push),删除的操作称为出栈(Pop)。
  • 队列:与堆栈类似,但是队列是先进先出(First In First Out),添加和删除分别称为入队和出队,这种先入先出的概念应用广泛。
  • 哈希表:将具有键值对的数据存储入空间中,将键通过哈希函数进行映射,得到哈希值,存储与读取都根据哈希值来进行,若哈希值相同发生冲突则使用链表存储新的数据,其具有较高的查询效率。
  • 堆:堆是一种树形结构,用于实现优先队列,取出的值要从最小值取出,树形结构每个顶点称为“结点。堆中每个结点最多有两个子节点,节点排序从上到下从左到右,排序规则为:子节点必大于父节点。
  • 二叉查询树:同样采用树形结构,排序规则有两条:每个节点的值均大于其左子树上任一节点的值;每个节点的值均小于其右子树上任一节点的值。因此树的最小值应该从顶端往左下寻找,而最大值应该从顶端往右下寻找。

2.排序算法

1.冒泡排序

从序列的最右边开始比较相邻两个数据的值,将小的向前置换,没过一步最小的数据都会向泡泡一样“浮”到最前面。

# 冒泡排序 复杂度O(n^2)
m_list = [5,9,3,1,2,8,4,7,6]
l = len(m_list)
for i in range(l):
    for j in range(l-1,i,-1):
        if m_list[j] < m_list[j-1]:
            m_list[j], m_list[j-1] = m_list[j-1], m_list[j]
print(m_list)
2.选择排序

从数据中找到最小的值,与数据最左端的值交换位置,不断重复。

# 选择排序 复杂度O(n^2)
list = [6,1,7,8,9,3,5,4,2]
l = len(list)
for i in range(l):
    for j in range(i,l):
        if list[j] < list[i]:
            list[j], list[i] = list[i], list[j]
print(list) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
3.插入排序

假定最左边的是已经排序好的,不断从右边取出数字与已经排序好的比较并插入到相应位置,直到全部完成排序。

#插入排序 复杂度O(n^2)
list = [5,3,4,7,2,8,6,1,9]
l = len(list)
for i in range(1,l):
    for j in range(1,i):
        if list[i] < list[0]:
            tmp = list[i]
            del list[i]
            list.insert(0, tmp)
        elif list[i] < list[j] and list[i] > list[j-1]:
            tmp = list[i]
            del list[i]
            list.insert(j, tmp)
print(list) # [1, 2, 4, 5, 3, 6, 7, 8, 9]
4.堆排序

先将数据存入堆中(按堆的方法排序),然后取其第一个即是最小值,将剩余数据重新排序,重复取最小值即可得到排序好的数据。

# 堆排序 复杂度O(nlogn)
list = [5,2,7,3,6,1,4]
def heap(list):
    n = len(list)
    for i in range(0,int(math.log(n,2))): 
        for j in range(0,n//2):
            k = 2*j+2 if 2*j+2 < n and list[2*j+2] < list[2*j+1] else 2*j+1   
            if list[j] > list[k]:
                (list[j],list[k]) = (list[k],list[j])      
l = len(list)
n_list= []
for i in range(0,l):
    heap(list)
    n_list.append(list[0])
    del list[0]
print(n_list)  #[1, 2, 3, 4, 5, 6, 7]
5.归并排序

将序列对半分直至每个序列只剩一个数据,再将子序列进行归并,归并时对比两个序列的第一个数据,将小的先并入大序列,不断比较两个序列的第一个数据直至某一个先为空,剩下的序列直接添加到归并好的序列中即可,不断重复直至全部归并完成。归并排序需要用到递归算法,即算法中继续使用算法。

# 归并排序 复杂度O(nlogn)
list = [6,4,3,7,5,1,2]
n = len(list)

def merge(left, right):
    n_list = []
    while len(left) > 0 and len(right) > 0:
        if left[0] <= right[0]:
            n_list.append(left.pop(0))
        else:
            n_list.append(right.pop(0))
    n_list += left
    n_list += right
    return n_list

def merge_sort(list):
    if len(list) == 1:
        return list
    mid_line = len(list)//2
    left = list[:mid_line]
    right = list[mid_line:]
    return merge(merge_sort(left),merge_sort(right))
list = merge_sort(list)
print(list) # [1, 2, 3, 4, 5, 6, 7]
6.快速排序

在序列中随机选择一个基准值(pivot),然后将剩下的其它数据分为比基准值大的部分和比基准值小的部分,再在各部分中再选基准值并进行比较、分割,直到最后某一部分只剩一个值或没有值时结束,该算法是一种递归算法。

#快速排序 复杂度O(nlogn)
list = [3,5,8,1,2,9,4,7,6]
def pivot_sort(list):
    if len(list) == 1 or len(list)==0:
        return list
    large = []
    small = []
    mid = len(list)//2
    for i in range(len(list)):
        if i == mid:
            continue
        if list[i] <= list[mid]:
            small.append(list[i])
        else:
            large.append(list[i])
    return merge(pivot_sort(small),list[mid],pivot_sort(large))

def merge(small, mid, large):
    a = []
    a.append(mid)
    list = small + a + large
    return list

list = pivot_sort(list)
print(list) # [1, 2, 3, 4, 5, 6, 7, 8, 9]

3.数组查找

1.线性查找

线性查找即遍历整个数组,对比是否有该数据。

# 线性查找 复杂度O(n)
list = [3,9,8,2,1,4,6,5,7]
num = input('please input the number to search')
for i in range(len(list)):
    if list[i] == int(num):
        print('the index of number %d is %d!'%(int(num), i))
        break
    elif i == len(list) -1:
        print('the number is not in this list!')
2.二分查找

对有序数组进行查找,查找时将查找区间分半,看中间的数据是否为查找的数,若不是则看查找的数据落在哪个区间,再继续分半直到找到需要查找的数值。

# 二分查找 复杂度O(logn)
list = [1,2,3,4,5,6,7,8,9]
num = int(input('please input the number to search'))
n_list = list
for i in range(int(math.log(len(list),2))+1):
    if len(n_list) == 0:
        print('no this number in the list')
        break
    mid = len(n_list)//2
    if num == n_list[mid]:
        print('the number is in the list')
        break
    if num >= n_list[mid]:
        n_list = n_list[mid+1:]
    else:
        n_list = n_list[:mid]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值