• 周六. 7 月 13th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

算法与数据结构

admin

11 月 28, 2021

算法

1、排序算法

  1. 冒泡排序
  2. 选择排序
  3. 插入排序
  4. 快速排序
  5. 希尔排序
  6. 计数排序

2、列表查找

从列表中查找指定的元素

  1. 顺序查找

    从列表第一个元素开始,顺序进行搜索,直到找到为止

  1. 二分查找

    从有序列表的候选区data[0: n]开始,通过对待查找的值与候选区中的值比较使候选区的值减半

数据结构与算法动态可视化

1. 算法的衡量标准

1. 时间复杂度

时间复杂度:程序执行的大概次数,使用O()来计

 logn == log2^n

 如何一眼判断时间复杂度:

  1. 循环减半的过程 ==》O(logn)

  2. 几次循环就是n的几次方的复杂度

2. 空间复杂度

用来评估算法内存占用大小的一个式子

2. 冒泡排序

首先列表每相邻两个数进行比较,如果前面的比后面的大,就交换两个数

# 冒泡排序
# 时间复杂度:O(n^2)
def bubble_sort(li):
    for i in range(len(li) - 1):  # 趟数
        flag = True
        for j in range(len(li) - 1 - i):  # 每一趟内层循环,每一趟确定一个比较次数-i
            if li[j] > li[j + 1]:  # 前面大于后面交换位置
                li[j], li[j + 1] = li[j + 1], li[j]
                flag = False
        if flag:  # 优化:如果一趟循环下来都没有要比较交换的位置说明原本就是顺序的,直接返回
            return

3. 选择排序

先选择一个数,默认该数是最小的放在第一的位置,然后再一次遍历取出所有的数与第一个数比较,如果比他大交换位置

# 选择排序
# 时间复杂度:O(n^2)
def select_sort(li):
    for i in range(len(li)):
        # 将取出的第一个默认是最小的
        minloc = i
        for j in range(i + 1, len(li)):
            # 循环比较后面的所有值与 第一个元素比较
            if li[minloc] > li[j]:
                # 如果比第一个元素小就换位置
                li[minloc], li[j] = li[j], li[minloc]

4. 插入排序

列表被分为有序区域无序区两个部分,最初有序区就一个元素,每次从无序区取出一个元素,插入到有序区的位置,直到无序区变空

# 插入排序
# 时间复杂度:O(n^2)
def insert_sort(li):
    # 将第一个元素作为有序区第一个元素
    for i in range(1, len(li)):
        # 将无序区中的元素取出拿一个变量存着
        tmp = li[i]
        # 获取取去的前一个元素的索引
        j = i - 1
        # 比较取出的元素与前面的所有元素
        while j >= 0 and li[j] > tmp:
            # 前面的值覆盖取出的值
            li[j + 1] = li[j]
            # 依次循环前面的所有值
            j = j - 1
        # 比较完j=-1跳出循环,将取出的值作为第一个
        li[j + 1] = tmp

5. 快速排序

取一个元素p(第一个元素),使p其归位,列表被p分为两部分,左边的都比p小,右边的比p大,最后递归完成排序

# 快速排序
# 时间复杂度:O(nlogn)
def quick_sort(li, left, right):
    # left与right是左右两边的索引
    if left < right:
        # 调用归为函数得到中间的索引
        mid = partition(li, left, right)
        # 递归减半左右两边
        quick_sort(li, left, mid-1)
        quick_sort(li, mid+1, right)


# 归为函数
def partition(li, left, right):
    # 将第一个元素取出
    tem = li[left]
    while left < right:
        # 判断右边的是否比取出的第一个元素大,如果大指针移动一位
        while left < right and li[right] >= tem:
            right = right - 1
        # 如果右边的比第一个小,将该元素赋值给左边
        li[left] = li[right]
        
        # 判断左边的元素是否比取出的元素小,如果小指针移动一位
        while left < right and li[left] <= tem:
            left = left + 1
        # 如果左边的比取出的大,将该元素赋值给刚右边元素的位置
        li[right] = li[left]
    # 当指针重合时,将取出的第一个元素放下在中间
    li[left] = tem
    mid = left  # 或者等于right,两边指针重合时
    return mid

# quick_sort(li, 0, len(li)-1)

6. 希尔排序

1、希尔排序是一种分组插入排序的算法

2、首先取一个整数d1 = n/2,将元素分为d1个组,每组相邻元素之间距离为d1,在各组内进行直接插入排序

3、再取第二个整数重复上述分组过程,直到di = 1,所有元素在用一个组内进行直接插入排序

4、希尔排序每一趟只是让元素接近有序,最后一趟使所有元素有序

时间复杂度:O(1.3n)

7. 计数排序

时间复杂度:O(n)

def count_sort(li):
    # 先生成比列表多一个的列表全是0
    count = [0 for i in range(len(li)+1)]
    # 将列表循环取出对应的count=1
    print(count)
    for i in li:
        count[i] += 1
    print(count)
    # 将原列表清空后再添加
    li.clear()
    # 枚举出count
    for k, v in enumerate(count):
        print(k, v)
        # 去除0和保证重复的数在里面
        for i in range(v):
            li.append(k)

8. 二分查找

时间复杂度:O(logn)

def bin_search(li, value, low, high):
    if low <= high:
        mid = (low + high) // 2
        if li[mid] == value:
            return mid
        elif li[mid] > value:
            return bin_search(li, value, low, mid-1)
        else:
            return bin_search(li, value, mid+1, high)
    else:
        return

数据结构

1、线性结构

就是能够用一根线串起来的数据结构

数组(列表)

1、申请数组的前提条件是:内存是连续的

2、int a[7] :代表声明一个数组是a,数组大小是7,数组的元素都是整型

一个数长度是4个字节所以7个是28个字节

3、如何申请内存:在C, C++ 语言中,mallco(28)申请28个字节,用完后要释放: free(284、如果 int a[7] = [1, 2, 3, 4, 5, 6, 7]  那如何知道 a[3] = 4的?

a[3] = 首地址(1000) + 索引(3) * 长度(4)= 1012--1015

5、首地址是保存在数组名中的

链表(约瑟夫问题、丢手绢问题)

数组要一块连续的内存空间来存储,对内存的要求比较高。如果我们申请一个 100MB 大小的数组,当内存中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于 100MB,仍然会申请失败。 而链表恰恰相反,它并不需要一块连续的内存空间,它通过“指针”将一组零散的内存块串联起来使用,所以如果我们申请的是 100MB 大小的链表,根本不会有问题。

 

发表回复