Python 数据结构与算法详解以及示例代码

一、二分查找

        首先建立一个列表(输入时确保数字有序),然后使用二分查找寻找要查找元素的下标。此处有两个知识点,一个是建立数字列表的推导式:

My_list = [int(i) for i in input().split()]

        其实也可以用input().split()转换为列表,然后用for循环将其转化为int类型赋值到一个新的空列表中,不过那样太麻烦了。然后是关于运算符,“//”是取整除,用二分查找时必须用整除,不然会报错为float不能作为下标,以下是二分查找的代码实现:

import sys
def EF(lis,find_val):
    low = 0
    high = len(lis)-1
    while low <= high:
        mid = (low+high) // 2  # //表示向下取整
        if find_val > lis[mid]:
            low = mid+1
        elif find_val < lis[mid]:
            high = mid-1
        elif find_val == lis[mid]:
            return mid
st1 = [int (i) for i in input().split()]
print(EF(st1,4)+1)

二分查找的效率为O(logN)

二、冒泡排序

步骤:

1.指向数组中相邻的两个元素(最开始是数组开头的两个元素),并比较它们的大小。

2.如果它们的顺序错了,就将它们两个的位置互换,如果顺序已经正确,就什么都不做。

3.将两个指针右移一格。重复第1、2步,直至指针到达数组末尾。

注意:这里的前三步骤其实是一个轮回,这个轮回结束后,最大值将被放到数组的最后,就好像最大的气泡冒出了水面一样。而冒泡排序就是不断地重复这一轮回的过程,直至整个数组的顺序正确。

以下是冒泡排序的代码实现,其实也可以用两个for循环进行排序:

import sys

st1 = [int(i) for i in input().split()]

def maopao_sort(list):
    un_sorted_len = len(list)-1
    sorted = False
    while not sorted:
        sorted = True
        for i in range(un_sorted_len):
            if list[i]>list[i+1]:
                sorted = False
                list[i],list[i+1] = list[i+1],list[i]
        un_sorted_len = un_sorted_len - 1

maopao_sort(st1)

print(st1)

冒泡排序的时间复杂度是O(N*2),也称二次时间,这个时间复杂度多出现于嵌套循环中,即两个for循环嵌套

三、选择排序

步骤:

1.从左到右检查数组的每个数字,找出值最小的那个,我建议你用一个单独的变量来记住检查过的数字的最小值。

2.知道本次检查的最小值后,将其与本次检查的起点交换位置,第一次是0,第二次是1,以此类推

3.重复前两步,直至整个数组排好序

import sys

st1 = [int(i) for i in input().split()]

def choose_sort(list):
    for i in range(len(list)):
        lowest_num = i
        for j in range(i+1,len(list)):
            if list[j] < list[lowest_num]:
                lowest_num = j
        if lowest_num != i:
            list[lowest_num],list[i] = list[i],list[lowest_num]

choose_sort(st1)
print(st1)

        选择排序的时间复杂度是O(N*2),但实际上它比冒泡排序的效率要快一倍左右,即实际的效率应为O(N*2/2),但大O记法忽略常数,所以与冒泡排序一样。

四、插入排序

步骤:

1.在第一轮里,先将索引1的值移走,用一个临时变量保存,这样索引一就有一个空位

2.将空隙左侧的每一个值与临时变量的值进行比较,如果左侧的值大于临时变量的值,就将该值右移一格,随着值右移,空隙会左移,如果遇到比临时变量小的值,或者空隙已经到达了数组的最左端,就结束平移阶段。

3.将临时变量放入空隙

4.重复前三个步骤,直至数组有序

import sys

st1 = [int(i) for i in input().split()]

def insert_sort(list):
    for i in range(1,len(list)):
        flag = i
        val = list[flag]
        while flag>0 and list[flag-1]>val: #list[flag]<val 从大到小
            list[flag] = list[flag-1]
            flag-=1
        list[flag] = val

insert_sort(st1)
print(st1)

        插入排序的时间复杂度为O(N*2),在最坏情况下是这样的,但在平均情况下,插入排序其实是优于前两种排序的。

五、快速排序

        为了省去重复编写排序算法的烦恼,大部分编程语言都有自己的排序函数,其中很多函数依赖的就是快速排序算法,尽管在最坏情况下它的时间复杂度与插入排序和选择排序差不多,但在平均情况下它的表现的确足够优异。

        快速排序依赖一个名为分区的概念,下面我们先对这个概念进行一下了解:

        分区指从数组随机选取一个值,用它为,将比它小的值放在它左边,比它大的值放在右边,从技术上讲,选任意值为轴都可以。

        具体步骤为:首先选取一个值为轴,可以选取最右边的值为轴,然后放置指针,它们应该分别指向除去轴元素的数组的最左和最右的元素。然后开始进行分区,步骤如下:

1、左指针逐个向右移动,遇到大于等于轴的值时停下

2、右指针逐个向左移动,遇到小于等于轴的值时停下

3、将两指针指向的值换位置

4、重复上述步骤,直至两指针重合或者左指针移动到右指针右边

5、将轴与左指针所指的值交换位置

        分区完成时,轴左侧的值肯定比轴小,右侧的值肯定比轴大,所以轴的位置也就确定了。需要注意的是,这仅仅是第一次分区,轴两侧肯定还有些数字的顺序是错误的,所以接下来要重复进行分区的操作。

        上面讲的是分区的具体步骤,而快速排序严重依赖分区,它的运行方式如下:

1、将数组分区,使轴到正确的位置上去

2、对轴左右两侧的数组递归重复第1、2步,也就是说两个子数组也需要各自进行分区,然后再分区再分区直至顺序正确。

3、当分出的子数组长度为0或1时,达到我们的要求,无需操作

        对于这一块的知识,个人认为了解其原理即可,你并不需要编写快速排序的程序,很多时候自己编写的不知道BUG出在哪的程序完全可以用一个sort函数替代。这会让你产生一种挫败感,不要为了编程而编程,前人的成果在那里放着呢,能用就用。

        快速排序的时间复杂度为O(NlogN),最坏情况下时间复杂度为O(N*2)

        我们一般谈算法的速度指的并不是时间,而是随着输入的增加,其运行时间将以什么样的速度增加。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值