几种排序算法的学习,利用Python和C实现

之前学过的都忘了,也没好好做过总结,现在总结一下。

时间复杂度和空间复杂度的概念:

1、空间复杂度:是程序运行所以需要的额外消耗存储空间,一般的递归算法就要有o(n)的空间复杂度了,简单说就是递归集算时通常是反复调用同一个方法,递归n次,就需要n个空间。

2、时间复杂度:一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f (n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。在各种不同算法中,若算法中语句执行次数为一个常数,则时间复杂度为O(1),另外,在时间频度不相同时,时间复杂度有可能相同,如T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。

按数量级递增排列,常见的时间复杂度有:

常数阶O(1),对数阶O(log2n),线性阶O(n),

线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),...,

目前我已经学过的排序算法包括

1、二次排序:

1、插入排序

2、选择排序

2、递归排序:

1、归并排序

2、快速排序

3、希尔排序

4、冒泡排序

一、冒泡排序

原理:  冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。

评价:是效率最低的一种排序算法。

时间复杂度:最差和平均均为O(n2)

稳定性:由于相等的元素不需要交换,所以比较稳定

代码:

C实现:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int msort(int array[],int n)
{
    int exchange = 0;
        int i,j;
        i=j=0;
    for(i=0;i<n;i++)
    {
        j=n-1;
        while(j > i)
        {
            int temp=0;
            //printf("%d",array[j]);
            if (array[j]<array[j-1])
            {
                temp = array[j];
                printf("%d",temp);
                array[j] = array[j-1];
                array[j-1] = temp;
                exchange = 1;
            }
            j=j-1;
        }
        if (exchange == 0)
            break;
    }
    for(i=0;i<n;i++)
        printf("%d\n",array[i]);
}

int main(void)
{
    int SIZE=9;
    int array[9]={5,2,8,2,7,9,10,20,15};
    int i=0;
    for(i=0;i<SIZE;i++)
        printf("%d\n",array[i]);
    msort(array,SIZE);
    return 0;
}

Python实现:

import timeit

def  msort(array):
    exchange=False
    for i in xrange(len(array)):
        j=len(array)-1
        while(j>i):
            if array[j]<array[j-1]:
                array[j-1],arra[j]=array[j],array[j-1]
                exchange=True
            j=j-1
        if exchange!=True:
            break

    print array

def main():
    array=list(range(0,10000))
    msort(array)

if __name__=="__main__":
    t=timeit.Timer("main()",‘from __main__ import main‘)
    print t.timeit(1)

二、选择排序

原理:简单点说就是从数组第一个位置开始,给每个位置在剩余的元素中都找到最小的值放上去。

评价:由于每次都要寻找最值,所以选择排序效率不高

时间复杂度:最坏,最优和平均时间复杂度都是O(n2).

稳定性:由于交换,可能导致相等元素的前后顺序发生变化,所以不稳定。比如举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了

代码:

C实现:

#include<stdio.h>
#include<stdlib.h>

void ssort(int array[],int n)
{
    int i,j;
    int small;
    for(i=0;i<n;i++)
    {
        small=i;
        for(j=i+1;j<n;j++)
        {
            if (array[j]<array[small])
                small=j;
        }
        int temp=0;
        if (small!=i)
        {
            temp=array[i];
            array[i]=array[small];
            array[small]=temp;
        }
    }
    for(i=0;i<n;i++)
        printf("%d ",array[i]);

}

int main(void)
{
    int array[7]={7,3,1,6,4,2,8};
    ssort(array,7);
}

Python实现:

def ssort(array):

    for i in xrange(0,len(array)):
        j=i+1
        small=i
        while j<len(array):
            if array[j]<array[small]:
                small=j;
            j+=1
        if i!=small:
            array[small],array[i] = array[i],array[small]

    return array

array=[2,62,7,3,8,1,1]
print ‘any‘,all(array)
print ssort(array)

三、插入排序:

原理:为当前有序序列插入元素,插入到正确的位置。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开 始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。

评价:对于比较有序的数组列表来说,效率是线性的,相当快。

稳定度:如果碰见一个和插入元素相 等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳 定的。

时间复杂度:最差的情况是逆序的,需要O(n2),平均也是O(n2),最优的是线性的。

C实现

#include<stdio.h>
#include<stdlib.h>

int isort(int array[],int n)
{
    int i=0;
    int j;
    for(i=1;i<n;i++)
    {
        int temp=array[i];
        for(j=i;j>0&&array[j-1]>temp;j--)
        {
            array[j]=array[j-1];
        }
        array[j]=temp;
    }
    for(i=0;i<7;i++)
    {
        printf("%d ",array[i]);
}
}

int main(void)
{
    int array[7]={8,2,7,1,9,3,0};
    int result[7];
    isort(array,7);
}

Python实现:

def isort(array):
    for i in xrange(1,len(array)):
        temp=array[i]
        j=i
        while j>0 and array[j-1]>temp:
            array[j]=array[j-1]
            j=j-1
        array[j]=temp
    return array

print isort([6,3,2,1,8,4])

四、归并排序

原理:采用分治法,将数组分成两部分元素,如此下去,知道只剩下一个元素,采用递归调用。两部分数组比较,需要一个临时数组,存储有序值。

评价:算法很快,但是需要分配临时数组,耗费内存。

稳定度:由于在比较时,两个相等值可以保证位置不变,所以是稳定的。

时间复杂度:最优,最差和平均都是O(nlogn)

代码:

Python:

def merge(L1,L2):
    sorted_array=[]
    while L1 and L2:
        if L1[0] <= L2[0]:
            sorted_array.append(L1.pop(0))
        else:
            sorted_array.append(L2.pop(0))
    if L1:
        sorted_array.extend(L1)
    if L2:
        sorted_array.extend(L2)
    return sorted_array

def mersort(array):
    if len(array)<=1:
        return array
    center=int(len(array)/2)
    return merge(mersort(array[:center]),mersort(array[center:]))

if __name__=="__main__":
    array=[8,20,15,4,6,3,7,2,1,9]
    print mersort(array)
    

五、快速排序

原理:和归并排序的思想是相同的,都采用分治法,但是不同的是需要选择一个基准数,根据基准数把数组分为两段,比基准数小的在左边,比基准数大的在右边。左右两边再分别采用这种方法,如此递归调用下去,知道只剩下一个元素。

评价:关键是找到基准数,基准数一般是随机选择三个值,选择中间值,或者选择数组第一个元素,但是如果第一个元素是最小的或最大的就糟糕了。

稳定性:不稳定。比如序列为 5 3 3 4 3 8 9 10 11, 现在基准元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法

时间复杂度:最坏的情况是O(n2),最好喝平均都是O(nlogn)

python实现:

import random

def partition(array,left,right):

    if right-left==1:
        if array[left]>array[right]:
            array[left],array[right]=array[right],array[left]
        return None

    base=array[left]
    big_index,small_index = left+1,right
    while big_index < small_index:
        while array[big_index] <= base and big_index < right:
            big_index += 1
        while array[small_index] >= base and small_index > left:
            small_index -=1
        if big_index < small_index:
            array[big_index],array[small_index] = array[small_index],array[big_index]
    array[left],array[small_index] = array[small_index],base
    return small_index

def qsort(array,left,right):
    if  right > left:
        mid=partition(array,left,right)
        if mid is not None:
            qsort(array,left,mid)
            qsort(array,mid+1,right)

if __name__=="__main__":
    array=[]
    for i in xrange(0,50):
        array.append(random.randint(0,30))
    qsort(array,0,(len(array)-1))
    print array

其实快速排对大数组很有效率,但如果小数组,插入排序比较好,经验表明,元素数目小于15时,可以改为插入排序

Python:

import random
from insert.isort import import isort
def partition(array,left,right):

    if right-left==1:
        if array[left]>array[right]:
            array[left],array[right]=array[right],array[left]
        return None

    base=array[left]
    big_index,small_index = left+1,right
    while big_index < small_index:
        while array[big_index] <= base and big_index < right:
            big_index += 1
        while array[small_index] >= base and small_index > left:
            small_index -=1
        if big_index < small_index:
            array[big_index],array[small_index] = array[small_index],array[big_index]
    array[left],array[small_index] = array[small_index],base
    return small_index

def qsort(array,left,right):
    if  right-left>15:
        mid=partition(array,left,right)
        if mid is not None:
            qsort(array,left,mid)
            qsort(array,mid+1,right)
    else:
        isort(array)

if __name__=="__main__":
    array=[]
    for i in xrange(0,50):
        array.append(random.randint(0,30))
    qsort(array,0,(len(array)-1))
    print array

六、希尔排序

原理:采用不同的步长,分别进行插入排序,直到步长为1.原理解释最直观的如下:

例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:

13 14 94 33 82

25 59 94 65 23

45 27 73 25 39

10

然后我们对每列进行排序:

10 14 73 25 23

13 27 94 33 39

25 59 94 65 82

45

将上述四行数字,依序接在一起时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:

10 14 73

25 23 13

27 94 33

39 25 59

94 65 82

45

排序之后变为:

10 14 13

25 23 33

27 25 59

39 65 73

45 94 82

94

最后以1步长进行排序(此时就是简单的插入排序了)。

评价:选择步长是关键,选择好了,比较快,一般步长初始选择数组长度除以2,一直除以2,一直到步长为1.

稳定度:不稳定,不同部分数组排序,很有可能打破相等元素的顺序。

时间复杂度:(摘抄):

需要大量的辅助空间,和归并排序一样容易实现。希尔排序是基于插入排序的一种算法, 在此算法基础之上增加了一个新的特性,提高了效率。希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(

),但是现今仍然没有人能找出希尔排序的精确下界。希尔排序没有快速排序算法快 O(n(logn)),因此中等大小规模表现良好,对规模非常大的数据排序不是最优选择。但是比O(

)复杂度的算法快得多。并且希尔排序非常容易实现,算法代码短而简单。 此外,希尔算法在最坏的情况下和平均情况下执行效率相差不是很多,与此同时快速排序在最坏的情况下执行的效率会非常差。专家们提倡,几乎任何排序工作在开始时都可以用希尔排序,若在实际使用中证明它不够快,再改成快速排序这样更高级的排序算法. 本质上讲,希尔排序算法是直接插入排序算法的一种改进,减少了其复制的次数,速度要快很多。 原因是,当n值很大时数据项每一趟排序需要的个数很少,但数据项的距离很长。当n值减小时每一趟需要和动的数据增多,此时已经接近于它们排序后的最终位置。 正是这两种情况的结合才使希尔排序效率比插入排序高很多。

Python实现:

def shsort(array):
    interval = len(array)/2
    while interval >= 1:
        i = interval
        while i < len(array):
            if array[i] < array[i-interval]:
                j=i-interval
                temp=array[i]
                while j >=0 and array[j] >temp:
                    array[j+interval]=array[j]
                    j-=interval
                array[j+interval]=temp
            i+=1
        interval/=2

    return array

if __name__=="__main__":

    array=[3,6,9,5,7,4,8,2,1]
    print shsort(array)

还有堆排序,基数排序,继续研究。

几种排序算法的学习,利用Python和C实现

时间: 2024-10-28 22:07:49

几种排序算法的学习,利用Python和C实现的相关文章

学习Java绝对要懂的,Java编程中最常用的几种排序算法!

今天给大家分享一下Java中几种常见的排序算法的Java代码 推荐一下我的Java学习羊君前616,中959,最后444.把数字串联起来!     ,群里有免费的学习视频和项目给大家练手.大神有空时也会带带大家的,学Java的过程中一定要多问多记,不要怕问题,要去主动的解决问题. 冒泡排序 选择排序 插入排序 归并排序 例如:降序排{10,5,9,6}分为{10,5},{9,6}然后{5,10},{6,9}然后完成 快速排序 就最后一个快速排序可能大家看不太懂,我就举个例子吧 开始输入以下数组

几种排序算法的C++实现——快速排序、堆排序、基数排序

排序算法是非常常见的面试笔试问题,考查的一个人的基本功,本文将一些排序做了C++的实现,就当是做个学习总结吧. 1.快速排序 快速排序的中心是填坑法,取一个数(这里选取第一个数)作为基准数temp,从队尾开始寻找第一个比基准数小的数a[j],交换a[j]和temp,然后队首开始查找第一个比temp大的数a[i],交换之,遍历的结果是当i>=j时,temp左边的数都小于temp,后边的数都大于temp,这个有点像归并排序.最后利用递归调用完成排序,代码如下: 1 void QuickSort(in

Java常见的几种排序算法-插入、选择、冒泡、快排、堆排等

本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排序.快速排序(重点).堆排序.归并排序等等.看下图: 给定数组:int data[] = {9,2,7,19,100,97,63,208,55,78} 一.直接插入排序(内部排序.O(n2).稳定) 原理:从待排序的数中选出一个来,插入到前面的合适位置. [java] view plain copy

总结N种排序算法及实现

排序算法是一个简单的问题,但在此问题上却有大量的研究!当前的排序算法通常按照如下四个方面进行分类(或是评价): 1.时间复杂度:一个排序算法的理想性能是O(n).一般而言,好的性能O(nlogn),坏的性能O(n2). 2.空间复杂度(内存使用量) 3.稳定性:稳定的排序算法会让原本有相等键值的记录维持原本的相对次序. 4.排序方式:插入.交换.选择.合并等 一.冒泡排序:这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端. 步骤:1.比较相邻的两个元素,如果第一个比第二个大,就

12种排序算法:原理、图解、动画视频演示、代码以及笔试面试题目中的应用

出处:http://blog.csdn.net/han_xiaoyang/article/details/12163251. 声明:版权所有,转载请注明出处,谢谢. 0.前言 从这一部分开始直接切入我们计算机互联网笔试面试中的重头戏算法了,初始的想法是找一条主线,比如数据结构或者解题思路方法,将博主见过做过整理过的算法题逐个分析一遍(博主当年自己学算法就是用这种比较笨的刷题学的,囧),不过又想了想,算法这东西,博主自己学的过程中一直深感,基础还是非常重要的,很多难题是基础类数据结构和题目的思想综

Python 数据分析(二 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识

Python 数据分析(二) 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识 第1节 groupby 技术 第2节 数据聚合 第3节 分组级运算和转换 第4节 透视表和交叉表 第5节 时间序列 第6节 日期的规范.频率以及移动 第7节 时区处理 第8节 时期及算术运算 第9节 重采样及频率转换 第10节 时间序列绘图 groupby 技术 一.实验简介 Python 数据分析(二)需要同学们先行学完 Python 数据分析(一)的课程. 对数据集进行分

13种排序算法详解

0.前言 从这一部分开始直接切入我们计算机互联网笔试面试中的重头戏算法了,初始的想法是找一条主线,比如数据结构或者解题思路方法,将博主见过做过整理过的算法题逐个分析一遍(博主当年自己学算法就是用这种比较笨的刷题学的,囧),不过又想了想,算法这东西,博主自己学的过程中一直深感,基础还是非常重要的,很多难题是基础类数据结构和题目的思想综合发散而来.比如说作为最基本的排序算法就种类很多,而事实上笔试面试过程中发现掌握的程度很一般,有很多题目,包括很多算法难题,其母题或者基本思想就是基于这些经典算法的,

常见的几种排序算法-插入、选择、冒泡、快排、堆排等

排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排序.快速排序(重点).堆排序.归并排序等等.看下图: 给定数组:int data[] = {9,2,7,19,100,97,63,208,55,78} 一.直接插入排序(内部排序.O(n2).稳定) 原理:从待排序的数中选出一个来,插入到前面的合适位置. package com.xtfggef.algo.sort; public

八种排序算法

最近一段时间自己在研究各种排序算法,于是自己写了一个八种排序算法的集合: /************************************************************************* > Copyright (c)2014 stay hungry,stay foolish !!! > File Name: sort.cpp > Author: kanty > Mail: [email protected] > Created Time: