分类
计算机

排序算法

最近在leetcode上刷题,想回顾一下计算机编程的基本功——算法。常用的排序算法(内部排序),按大类分可分为以下几种:插入排序、交换排序、选择排序、归并排序和计数排序五大类。下面用Python代码简单实现一下这几种排序算法。

插入排序

插入排序(Insertion Sort)比较简单直观,原理是将为排序数据,在已排序序列中从后往前扫描,找到相应位置插入。

直接插入排序(Straight Insertion Sort)

def insertion_sort(nums):
    for i in range(1, len(nums)):
        j, key = i - 1, nums[i]
        while j >= 0 and key < nums[j]:
            nums[j+1] = nums[j]
            j = j - 1

        nums[j+1] = key

希尔排序(Shell Sort)

def shell_sort(nums):
    length = len(nums)
    n = length // 2
    while n > 0:
        for i in range(n, length):
            j = i - n
            while j >= 0:
                if nums[j] > nums[j + n]:
                    nums[j], nums[j + n] = nums[j + n], nums[j]
                j = j - n
        n = n // 2
    return nums

交换排序

交换排序也是一种非常基础的算法,主要包含冒泡排序和快速排序。

冒泡排序(Bubble Sort)

def bubble_sort(nums):
    for i in range(0, len(nums)-1):
        swapped = False
        for j in range(0, len(nums)-1-i):
            if nums[j] > nums[j+1]:
                nums[j], nums[j+1] = nums[j+1], nums[j]
                swapped = True
        if not swapped:
            break
    return nums

快速排序(Quick Sort)

快速排序,又称分区交换排序,简称快排,是对冒泡排序的一种改进。

def quick_sort(nums, low, high):
    if low >= high: return

    pivot = nums[low]  # 选数列第一个元素作为"基准"
    i, j = low, high
    while i < j:
        while i < j and nums[j] >= pivot:
            j = j - 1
        nums[i] = nums[j]

        while i < j and nums[i] <= pivot:
            i = i + 1
        nums[j] = nums[i]
    nums[i] = pivot

    quick_sort(nums, low, i-1)
    quick_sort(nums, i+1, high)

选择排序

简单选择排序(Selection Sort)

def selection_sort(nums):
    for i in range(0, len(nums) - 1):
        min_index = i
        for j in range(i + 1, len(nums)):
            if nums[j] < nums[min_index]:
                min_index = j
        nums[i], nums[min_index] = nums[min_index], nums[i]
    return nums

堆排序(Heap Sort)

def heap_sort(nums):
    # 堆调整
    def max_heapify(nums, i, length):
        parent = i
        child = 2 * i + 1
        if child >= length:
            return
        if child + 1 < length and nums[child] < nums[child+1]:
            child += 1
        if nums[parent] < nums[child]:
            nums[parent], nums[child] = nums[child], nums[parent]
            max_heapify(nums, child, length)
    
    # 初始化,构造大顶堆
    for i in range(len(nums) // 2 - 1, -1, -1):
        max_heapify(nums, i, len(nums))

    # 堆排序
    for j in range(len(nums) - 1, 0, -1):
        nums[0], nums[j] = nums[j], nums[0]
        max_heapify(nums, 0, j)

归并排序(Merge Sort)

快速排序虽然排序效率高,但是不稳定,时间复杂度介于O(nlogn)跟O(n2)之间。
而归并排序可以稳定在O(nlogn)。

def mergeSort(nums):
    if len(nums) == 1: 
        return nums

    mid = len(nums) // 2
    left = mergeSort(nums[:mid])
    right = mergeSort(nums[mid:])
    result = []
    while left and right:
        if left[0] <= right[0]:
            result.append(left.pop(0))
        else:
            result.append(right.pop(0))
    if left:
        result += left
    if right:
        result += right
    return result

参考

分类
摄影

国家植物园

上周末去了一趟国家植物园。这是更名后第一次来游玩,其实就是在原来北京植物园的基础上,合并了原来的中国科学院植物研究所(南园)。

下面直接放图。
分类
摄影

颐和园

2021年1月16号,周六,微风,有点冷。去了一趟颐和园,拍了一些照片。来北京已经去过好几趟颐和园,这是第N次。下面就放几张照片。

分类
旅行

2016西安之行

2016年十一假期,我和同学去了一趟西安。在去西安前我们做了一些攻略,为了不让此次旅途留下遗憾,我们把华山也规划到了行程中。

第一站:华山

在经历了一个晚上后,在东峰等来的日出。

到西安第一天我们就去了华山,上面这张图是在东峰看的日出。整个爬山过程可以说非常“艰辛”,毕竟这是一座海拔2000米以上的山。加上十一期间天气比较热,旅游旺季人特别多,不过人多也热闹?。

售票大厅门前人山人海
售票大厅旁边的华山全景图

华山景区售票大厅前,人山人海,我们在30多度的高温下排了2-3个小时队才买到票。上去华山有两个途径:一是坐缆车直接上去,二是徒步攀登上去。我们当然选择爬上去,坐缆车就失去了爬山的乐趣。爬山的入口跟售票处不在一个地方,需要坐摆渡车到玉泉院。

玉泉院,就是一个道教寺庙。
旁边还有一个卧着的道士石像。

进到玉泉院,一股比较浓烈的香火味。有人在这里烧香拜佛。另外有一些人,也是来爬华山,先在这里稍作休息。因为要夜爬,经历的时间比较长,所以不用着急早早上去。

穿过玉泉院,后边就是华山登山的入口。入口处一些老人在卖红绳,绑上一根可以保佑你爬山平安,相当于一个平安符。

老人在给我的同学系红绳
在山下给同学照的一张照片
华山门(忽略带墨镜的哥们)

进华山门,就正式开始爬华山了。在过华山门的时候不仅要验票,还要录入每个人的指纹。这个应该是为了防止游客发生意外或者走失,看来爬华山还是有一定危险的。

沿途拍的一些华山风景,和一道爬山的人们。

一位爬华山的小朋友
山上留下来的溪水
五里关
沿途一座道教寺庙
景区里的小摊贩

景区里的小摊贩,卖的东西价格贵的吓人。山下还好,到了山上就真的贵的离谱,一瓶矿泉水卖到10块钱。

途中拍了一张华山照片,分不清是哪个峰。
一路上能经常看到铁栏杆上挂着一把把锁和许多红绳,应该是祈求爱情能长长久久吧。
红绳和锁
一块巨石压在过道上边
太阳照山顶
华山的地貌很有特点,大部分裸露的山体以及接近垂直的山坡
半山腰有一个亭子

从这个角度看,华山是不是有点像美国优胜美地国家公园

华山仙境
同学和“仙境”合影
走了一大段路后,感觉离山顶近了一点。还得继续走。

走到一处景区导览图。距离山顶还有一大段距离要走。

到了整个爬山过程中最陡峭的路了,百尺峡。另外还有一个地方是千尺幢。其实这样陡峭的路还有很多,只不过这两个让人印象深刻,台阶陡峭度接近8-90度。从上往下看特别吓人。

大家必须得牢牢抓住铁链,才敢继续往上走。

过了这一段,基本上就快到达山顶了。接下来的路就相对比较平缓,天也快黑了。

太阳落山了。
远处城市的灯光也开始亮起来了。

华山是一个可以夜爬的山,所以天黑后,路上就开始亮灯了。爬山的进程可以继续。

晚上的爬山路上全是年轻人,十分热闹。这也是爬华山有意思的地方,就是热闹。

晚上山顶灯火通明

我们继续走了一段后,到达华山北峰山顶。

华山论剑

华山北峰顶上的“华山论剑”,许多人在这照相留念。

夜晚的华山

我用相机长曝光照了对面的山(可能是东峰)。这个时候四周已经黑到肉眼看不清了,可以看到照片上全是噪点和光污染,可以知道光线有多弱。

华山的“夜市”

这会是大概是晚上8-9点多,山上人特别多也非常热闹,像个夜市。有人在华山顶上拍照,有人摆摊卖东西,有人搭帐篷准备休息。我和同学稍微停留了一下就继续前行。因为我们还要去东峰看日出。从北峰坡顶到东峰还有很长一段距离。

随手照了一张夜景照

这天山上风特别大,可以看到树在剧烈摇晃。我们第二天收到腾讯新闻说华山顶上是9级大风。

一张星空照

在山顶用相机长曝光,拍了一张星空。因为光污染比较多,效果不是特别好。

山上有客栈可以休息,但是价格高的一般人消费不起。我们也就看看,住是不可能住下的。

打开手机指南针应用,显示海拔2060米。

大概后半夜2-3点我们到华山的东峰,这个时候已经冷得不行。在山下白天还是30多度的情况,到了山上,凌晨的时候,气温就快接近0度。我们以为做了足够准备,带了一件外套,但是明显不够。冻的不行。还好山上有一些餐馆,可以让你免费待在里边。

餐馆里挤满了人

又过了大概2-3个小时,差不多天快亮了。

天边有点微光
山头挤满了人

大家都跑到外边,等待日出。

天慢慢变亮