《算法图解》读书笔记-2选择排序(数组与链表)

数组和链表

链表:链表中的元素可储存在内存的任何地方,也就是说可以不连续。链表的每个元素都存储了下一个元素的地址,从而使一系列随机的内存串在一起。它的优势是插入方面比较快。
链表

补充知识:其实链表分为单链表和双链表(此图出处)。
单、双链表

说出来你可能不信对于链表的介绍就像开玩笑一样的结束了。。。。。。
但是为了加强下印象简单实现个单链表结构,大佬勿喷。。。

class Node(object):
    def __init__(self, value=None, next=None):
        '''首先需要个节点,包括value和next属性'''
        self.value, self.next = value, next

class LinkedList(object):
    '''简单的实现下append方法'''
    def __init__(self, maxsize=None):
        self.maxsize = maxsize    #链表最大长度   默认为None表示无限制(只要内存够用)
        self.length = 0            #长度
        self.root = Node()     #定义根节点(链表起始)
        self.tailnode = None  #尾结点

    def __len__(self):
        return self.length

    def append(self, value):
        if self.maxsize is not None and len(self) >= self.maxsize:#首先判断一波链表是否满了
            raise Exception("Full")
        node = Node(value)      #将加入的值  定义成节点
        tailnode = self.tailnode      #获取到尾结点

        if tailnode is None:          #判断是否只有root节点
            self.root.next = node      #如果只有根结点正好  根节点直接指向该值
        else:
            self.tailnode.next = node   #否则尾结点指向该值
        self.length += 1
        self.tailnode = node        #一定要更新尾结点

  

数组

数组:其实数组相对好理解,就是将一组数据连续存储,数组的元素是带着标号的,地址是互相挨着的。

数组

链表和数组的操作运行时间如下:
对比如上

  • 如果删除元素,链表只需要修改前一个元素指向的地址即可。而数组在删除元素后,必须将后面的元素向前移动。
  • 读取的时候链表只能重头访问所以查询不如数组灵活。

##选择排序

问题:假设计算机内存储了许多音乐,并且记录了被播放的次数,需要按照次数进行排序该如何去做?
如图

首先考虑最笨的做法(选择排序):每次都看一遍所有数据,假设一共有n个数据,需要看n次并且每次看n个数据,由于O(n)表示的是将每个数据看一遍,所以此操作复杂度为O( n 2 n^2 n2)。

# encoding: utf-8
# @Author : NanG
# create on 2020-03-17 08:59
from datetime import datetime

import numpy as np


def findSmallest(arr):
    smallest = arr[0]     #最小值(也可以最大值)
    smallest_index = 0    #最小值索引
    for i in range(1, len(arr)):
        if arr[i] < smallest:
            smallest = arr[i]
            smallest_index = i
    return smallest_index


def selectionSort(arr):
    startime = datetime.timestamp(datetime.now())
    newArr = []
    for i in range(len(arr)):
        smallest = findSmallest(arr)
        newArr.append(arr.pop(smallest))
    endtime = datetime.timestamp(datetime.now())

    return newArr,  endtime-startime


def test_selectionSort():
    arrs1 = np.random.randint(10, size=100)
    test10, time10 = selectionSort(list(arrs1))
    print("time100:{}".format( time10))
    print(test10)

    arrs2 = np.random.randint(10, size=1000)
    test100, time100 = selectionSort(list(arrs2))
    print("time100:{}".format( time100))

    arrs3 = np.random.randint(10, size=10000)
    test1000, time1000 = selectionSort(list(arrs3))
    print("time10000:{}".format(time1000))

    arrs4 = np.random.randint(10, size=100000)
    test1000000, time1000000 = selectionSort(list(arrs4))
    print("time100000:{}".format(time1000000))

    arrs4 = np.random.randint(10, size=1000000)
    test1000000, time1000000 = selectionSort(list(arrs4))
    print("time1000000:{}".format(time1000000))
if __name__ == '__main__':
    test_selectionSort()

本来想用传说中的五点确定图像的方法(初中画图基础),但是1000000的计算了一个多小时还没结束,有些心疼我的小笔记本就没做完。结果如下(建议用pytest进行单测):

time100:0.0004849433898925781
time1000:0.049310922622680664
time10000:4.410588026046753
time100000:453.7767798900604
time1000000:>1小时



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值