排序算法

  1. 冒泡排序:
  1. 算法分析:

对一组数据两两进行比较, 如果左边小于右边,则交换,这样每次将最大的一个数放在最后,即将大数冒出。对于N个数,一共需要N-1轮, 每一轮次需要比较N-1-(轮数)次。这里我用到了一个优化,例如8, 2, 3, 5, 7这一组数,第一次排序过后将大数挪至最后,就变成:2, 3, 5, 7, 8;就已经排好序了,就无需在进行接下来的循环比较了, 所以在每一轮次循环比较的时候, 设置一个标识, 当没有可交换的数时, 即为排好了, 就退出,节省时间。

  1. 算法实现:

  1. 选择排序:
  1. 算法分析:

选择排序是每次在数组中选择一个最小的数放在对应位置上,即第一选择的是整个数组中最小的数,和第一位交换,第二次在剩下的数中选择一个最小的和第二位交换,以此类推,相比较冒泡排序,他少了很多比较交换的次数,因此比冒泡排序快。

  1. 算法实现:

  1. 插入排序:
  1. 算法分析:

插入排序的思想就是在已排好的序列中,将数插入到合适的位置,就跟理扑克牌一样。算法实现上,开始将数组划分为两个部分,第一个数作为已排好的的序列,第二个数往后为待插入的序列。每次选择出一个待插入数,依次向前面已排好的序列作比较,若待插入数与当前比较的数小,则将当前数后移,直到找到一个比他还小的数,就将当前数插入到该位置。

  1. 算法实现:

  1. 快速排序:
  1. 算法分析:

第一步,选择一个数作为基准,将所有比基准还小的数放在基准的左边,比基准大的数放在基准右边,这样就把数组划分为了两部分,第二步,对前一部分和后一部分进行递归划分,直到有序。

  1. 算法实现:

 

  1. 所有算法实现代码(python):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : BubbleSort.py
# @Author: deng
# @Date  : 2018/11/29 10:30
# @Desc  :

import time
import numpy as np
import psutil
import matplotlib.pyplot as plt


class Sort(object):
    """排序类的基类"""
    def __init__(self, desc=False, show=True, name="Sort"):
        self.arr = None  # 待排序的数组
        self.desc = desc  # 是否按照降序
        self.show = show  # 是否显示排序结果及详细
        self.arr_size = 0  # 数组大小
        self.name = name  # 排序名称
        self.time = None  # 所用时间
        self.memory = None  # 内存占用情况

    def get_time(self):
        return self.time

    def sorted(self, arr):
        pass

    def descSort(self):
        for i in range(self.arr_size // 2):
            head, tail = 0, self.arr_size - 1
            self.arr[head], self.arr[tail] = self.arr[tail], self.arr[head]
            head += 1
            tail -= 1

    def describe(self):
        # print("---排序结果---")
        # print(self.arr)
        descb = {"排序名称": self.name, "数据规模": self.arr_size, "耗时": self.time, "内存": self.memory}
        print(descb)


class BubbleSort(Sort):
    """冒泡排序"""
    def __init__(self, desc=False, show=True):
        Sort.__init__(self, desc, show, "BubbleSort")

    def sorted(self, arr):
        self.arr = arr
        self.arr_size = len(arr)
        self.bubSort()
        # 如果是降序
        if self.desc:
            self.descSort()
        if self.show:
            self.describe()

    def bubSort(self):
        """排序的具体算法"""
        start_time = time.time()
        if self.arr_size > 0:
            for i in range(1, self.arr_size):
                """需要比较的轮数, 10个数需要比较9次, 一次类推"""
                # 标识有没有可交换的数,初始为False
                exchange = False
                for j in range(self.arr_size - i):
                    """每一轮需要交换的次数"""
                    if self.arr[j] > self.arr[j + 1]:
                        # 交换
                        self.arr[j], self.arr[j + 1] = self.arr[j + 1], self.arr[j]
                        exchange = True
                # 当没有可交换的数时,退出循环
                if not exchange:
                    break
        end_time = time.time()

        self.time = end_time - start_time  # 计算耗时
        # 计算内存
        self.memory = round(psutil.virtual_memory().used/1024/1024/1024, 3)


class SelectSort(Sort):
    """选择排序"""
    def __init__(self, desc=False, show=True):
        Sort.__init__(self, desc, show, name="SelectSort")

    def sorted(self, arr):
        """具体算法"""
        self.arr = arr
        self.arr_size = len(arr)
        start_time = time.time()
        for i in range(0, self.arr_size):
            # 每次假定当前值为最小值
            index = i
            for j in range(i+1, self.arr_size):
                """遍历找到一个最小的"""
                if self.arr[j] < self.arr[index]:
                    index = j
            # 交换
            self.arr[i], self.arr[index] = self.arr[index], self.arr[i]
        end_time = time.time()

        self.time = end_time - start_time  # 计算耗时
        self.memory = round(psutil.virtual_memory().used / 1024 / 1024 / 1024, 3)
        if self.desc:
            self.descSort()
        if self.show:
            self.describe()


class InsertSort(Sort):
    """插入排序"""
    def __init__(self, desc=False, show=True):
        Sort.__init__(self, desc, show, name="InsertSort")

    def sorted(self, arr):
        self.arr = arr
        self.arr_size = len(arr)
        start_time = time.time()
        # 从第二个数开始往前面的进行插入
        for i in range(1, self.arr_size):
            insert = self.arr[i]  # 待插入的数
            j = i - 1
            # 在前面已排好的数中找到插入位置
            while j >= 0 and self.arr[j] > insert:
                self.arr[j+1] = self.arr[j]
                j -= 1
            self.arr[j+1] = insert

        end_time = time.time()
        self.time = end_time - start_time  # 计算耗时
        self.memory = round(psutil.virtual_memory().used / 1024 / 1024 / 1024, 3)
        if self.desc:
            self.descSort()
        if self.show:
            self.describe()


class QuickSort(Sort):
    """快速排序"""
    def __init__(self, desc=False, show=True, name="QuickSort"):
        Sort.__init__(self, desc, show, name)

    # 划分区域
    def partiton(self, low, high):
        # 选择第一个数为基准
        key = self.arr[low]
        while low < high:
            # 从后往前搜索,把所有比基准小的数放到基准的左边
            while low < high and self.arr[high] >= key:
                high -= 1
            if low < high:  # 交换
                self.arr[low], self.arr[high] = self.arr[high], self.arr[low]
            # 从前往后搜索,把所有比基准大的数放在基准右边
            while low < high and self.arr[low] <= key:
                low += 1
            if low < high:
                self.arr[high], self.arr[low] = self.arr[low], self.arr[high]
        # 划分完成后就把数组分为了两部分,返回基准所在的位置, 即左边都是比基准小的数,右边都是比基准大的数
        return low

    def quickSort(self, low, high):
        if low >= high:
            return
        # 划分区域后返回基准的位置
        center = self.partiton(low, high)
        # 递归对左边在进行划分
        self.quickSort(low, center - 1)
        # 递归对右边在进行划分
        self.quickSort(center + 1, high)

    def sorted(self, arr):
        self.arr = arr
        # 开始时间
        self.arr_size = len(arr)
        start_time = time.time()
        self.quickSort(0, self.arr_size - 1)
        # 结束时间
        end_time = time.time()
        self.time = end_time - start_time  # 计算耗时
        self.memory = round(psutil.virtual_memory().used / 1024 / 1024 / 1024, 3)
        if self.desc:
            self.descSort()
        if self.show:
            self.describe()


if __name__ == '__main__':

    # 测试的数据规模
    temp = [i for i in range(10, 1000, 10)]
    size = [i for i in range(1000, 21000, 1000)]
    size = temp+size
    # 画图用的
    color = ['r', 'g', 'c', 'b']

    # 创建各个排序对象
    bs = BubbleSort()
    ss = SelectSort()
    Is = InsertSort()
    qs = QuickSort()
    # 放到集合里
    objs = [qs, ss, Is, bs]

    # 测试排序
    for obj, c in zip(objs, color):
        times = []
        for i in size:
            # 初始随机数 i 为数据规模大小
            num = np.random.randint(1, 100000, i)
            obj.sorted(num)
            times.append(obj.get_time())
            # 删除随机数组,防止内存溢出
            del num
        # 标注坐标轴
        plt.xlabel("size")
        plt.ylabel("time")
        # 画图
        plt.plot(size, times, "-", color=c, label=str(obj.name))
    plt.legend(loc="upper left")
    plt.grid(True)
    plt.show()





  1. 运行结果:

 

D:\Anaconda\python.exe E:/我的程序设计/Python/PythonProject/homework/Sort/Sort.py

{'排序名称': 'QuickSort', '数据规模': 10, '耗时': 0.0, '内存': 3.571}

{'排序名称': 'QuickSort', '数据规模': 100, '耗时': 0.0010030269622802734, '内存': 3.571}

{'排序名称': 'QuickSort', '数据规模': 1000, '耗时': 0.00601649284362793, '内存': 3.571}

{'排序名称': 'QuickSort', '数据规模': 10000, '耗时': 0.09826040267944336, '内存': 3.575}

{'排序名称': 'QuickSort', '数据规模': 20000, '耗时': 0.16748738288879395, '内存': 3.576}

{'排序名称': 'SelectSort', '数据规模': 10, '耗时': 0.0, '内存': 3.584}

{'排序名称': 'SelectSort', '数据规模': 100, '耗时': 0.001001596450805664, '内存': 3.584}

{'排序名称': 'SelectSort', '数据规模': 1000, '耗时': 0.14438295364379883, '内存': 3.584}

{'排序名称': 'SelectSort', '数据规模': 10000, '耗时': 14.381277799606323, '内存': 3.585}

{'排序名称': 'SelectSort', '数据规模': 20000, '耗时': 56.96345281600952, '内存': 3.562}

{'排序名称': 'InsertSort', '数据规模': 10, '耗时': 0.0, '内存': 3.562}

{'排序名称': 'InsertSort', '数据规模': 100, '耗时': 0.0010035037994384766, '内存': 3.562}

{'排序名称': 'InsertSort', '数据规模': 1000, '耗时': 0.11129498481750488, '内存': 3.562}

{'排序名称': 'InsertSort', '数据规模': 10000, '耗时': 11.534623622894287, '内存': 3.561}

{'排序名称': 'InsertSort', '数据规模': 20000, '耗时': 47.08919715881348, '内存': 3.557}

{'排序名称': 'BubbleSort', '数据规模': 10, '耗时': 0.0, '内存': 3.557}

{'排序名称': 'BubbleSort', '数据规模': 100, '耗时': 0.00200653076171875, '内存': 3.557}

{'排序名称': 'BubbleSort', '数据规模': 1000, '耗时': 0.2827944755554199, '内存': 3.557}

{'排序名称': 'BubbleSort', '数据规模': 10000, '耗时': 28.376445531845093, '内存': 3.555}

{'排序名称': 'BubbleSort', '数据规模': 20000, '耗时': 114.53751921653748, '内存': 3.548}

 

  1. 时间对比:

横轴:数据规模大小

纵轴:耗时(单位:s)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值