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

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

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 = ;
int i,j;
i=j=;
for(i=;i<n;i++)
{
j=n-;
while(j > i)
{
int temp=;
//printf("%d",array[j]);
if (array[j]<array[j-])
{
temp = array[j];
printf("%d",temp);
array[j] = array[j-];
array[j-] = temp;
exchange = ;
}
j=j-;
}
if (exchange == )
break;
}
for(i=;i<n;i++)
printf("%d\n",array[i]);
} int main(void)
{
int SIZE=;
int array[]={,,,,,,,,};
int i=;
for(i=;i<SIZE;i++)
printf("%d\n",array[i]);
msort(array,SIZE);
return ;
}

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=;i<n;i++)
{
small=i;
for(j=i+;j<n;j++)
{
if (array[j]<array[small])
small=j;
}
int temp=;
if (small!=i)
{
temp=array[i];
array[i]=array[small];
array[small]=temp;
}
}
for(i=;i<n;i++)
printf("%d ",array[i]); } int main(void)
{
int array[]={,,,,,,};
ssort(array,);
}

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=;
int j;
for(i=;i<n;i++)
{
int temp=array[i];
for(j=i;j>&&array[j-]>temp;j--)
{
array[j]=array[j-];
}
array[j]=temp;
}
for(i=;i<;i++)
{
printf("%d ",array[i]);
}
} int main(void)
{
int array[]={,,,,,,};
int result[];
isort(array,);
}

Python实现:

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

四、归并排序

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

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

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

时间复杂度:最优,最差和平均都是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)

七、基数排序

原理:又名桶子排序,有10个桶。首先把个位数按照顺序放到桶子中,个位数相同的就放在同一个桶子里;然后再按照十位数的大小顺序放到桶子里,依次类推,最后得到结果。

评价:基数排序的时间复杂度是 O(k·n),其中n是排序元素个数,k是数字位数。注意这不是说这个时间复杂度一定优于O(n·log(n)),k的大小取决于数字位的选择(比如比特位数),和待排序数据所属数据类型的全集的大小;k决定了进行多少轮处理,而n是每轮处理的操作数目。

以排序n个不同整数来举例,假定这些整数以B为底,这样每位数都有B个不同的数字,k = logB(N),N是待排序数据类型全集的势。虽然有B个不同的数字,需要B个不同的桶,但在每一轮处理中,判断每个待排序数据项只需要一次计算确定对应数位的值,因此在每一轮处理的时候都需要平均n 次操作来把整数放到合适的桶中去,所以就有:

  • k 约等于 logB(N)

所以,基数排序的平均时间T就是:

T ~= logB(Nn

其中前一项是一个与输入数据无关的常数,当然该项不一定小于logn

稳定度:很稳定.基数排序基于分别排序,分别收集,所以其是稳定的排序算法

时间复杂度:O(k·n)

Python实现:

def rsort(array):
length = len(str(max(array)))
locat = 0
while locat < length:
bucket = []
for n in xrange(0,10):
bucket.append([])
for i in array:
index=i%10 if not locat else i/(locat*10)%10
bucket[index].append(i) array = []
for i in bucket:
array.extend(i)
locat += 1
return array print rsort([35,8611,84,36,745,154,39,4,3])

八、堆排序

原理:构成堆,将末端值与根节点交换

稳定度:不稳定

时间复杂度:nlogn

Python实现:

def make_heap(array,start,end):
lchild = lambda x:2*x+1
rchild = lambda x:2*x+2
root = start
while True:
left = lchild(root)
if left > end:
break
right = rchild(root)
child = right if right <= end and array[left]<array[right] else left
if array[child] <= array[root]:
break
else:
array[root],array[child] = array[child],array[root]
root = child def list_heap(array):
for i in xrange(len(array)/2,-1,-1):
make_heap(array,i,len(array)-1) def hsort(array):
list_heap(array)
for end in xrange(len(array)-1,0,-1):
array[0],array[end] = array[end],array[0]
make_heap(array,0,end-1)
return array

if __name__=="__main__":

array=[3,7,1,8,230,56,100,34,12,40,9,54,67,24,26]
   print hsort(array)

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

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

    今天给大家分享一下Java中几种常见的排序算法的Java代码 推荐一下我的Java学习羊君前616,中959,最后444.把数字串联起来!     ,群里有免费的学习视频和项目给大家练手.大神有空时也 ...

  2. 史上最全单链表的增删改查反转等操作汇总以及5种排序算法(C语言)

    目录 1.准备工作 2.创建链表 3.打印链表 4.在元素后面插入元素 5.在元素前面增加元素 6.删除链表元素,要注意删除链表尾还是链表头 7.根据传入的数值查询链表 8.修改链表元素 9.求链表长 ...

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

    Python 数据分析(二) 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识 第1节 groupby 技术 第2节 数据聚合 第3节 分组级运算和转换 第4 ...

  4. C#常用8种排序算法实现以及原理简介

    public static class SortExtention { #region 冒泡排序 /* * 已知一组无序数据a[1].a[2].--a[n],需将其按升序排列.首先比较a[1]与a[2 ...

  5. 排序—时间复杂度为O(n2)的三种排序算法

    1 如何评价.分析一个排序算法? 很多语言.数据库都已经封装了关于排序算法的实现代码.所以我们学习排序算法目的更多的不是为了去实现这些代码,而是灵活的应用这些算法和解决更为复杂的问题,所以更重要的是学 ...

  6. 8种排序算法 Java实现

    冒泡排序 O(n2) 两个数比较大小,较大的数下沉,较小的数冒起来. public static void bubbleSort(int[] a) { //临时变量 int temp; //i是循环次 ...

  7. JavaScript实现的7种排序算法

    所谓排序算法,即通过特定的算法因式将一组或多组数据按照既定模式进行重新排序.这种新序列遵循着一定的规则,体现出一定的规律,因此,经处理后的数据便于筛选和计算,大大提高了计算效率.对于排序,我们首先要求 ...

  8. 秒杀9种排序算法(JavaScript版)

    一:你必须知道的 1> JS原型 2> 排序中的有序区和无序区 3> 二叉树的基本知识 如果你不知道上面三个东西,还是去复习一下吧,否则,看下面的东西有点吃力. 二:封装丑陋的原型方 ...

  9. PHP的几种排序算法的比较

    这里列出了几种PHP的排序算法的时间比较的结果,,希望对大家有所帮助 /* * php 四种排序算法的时间与内置的sort排序比较 * 3000个元素,四种算法的排序所用的时间比较 * 冒泡排序 85 ...

随机推荐

  1. Java方法trim()小记

    我们一般用trim()方法的主要作用,是为了去除字符串的首尾空格.然而根据我个人的实践经验发现,trim()这个方法只能去除部分的空格或空白符,比如半角空格:对于全角空格的话,用trim()并不能去除 ...

  2. 不完全解决Android微信HTML5 播放视频的问题(不显示控制条,可交互)

    首先你需要知道以下内容: http://ad.weixin.qq.com/learn/2-3-3--%E9%80%9A%E7%94%A8%E5%BA%93 这是微信为广告商开放的API,我一直认为只有 ...

  3. sublime-text3 3059基本配置

    1.下载安装官方版注册机语言包 参考安装: http://www.xiumu.org/note/sublime-text-3.shtml 2.插件 Package ControlConvertToUT ...

  4. html4,xhtml,html5发展历史

    SGML SGML 是一种很强大但很复杂的标记语言,HTML.XML 就是从中衍生出来的.SGML 的例子如下:<QUOTE TYPE="example"> typic ...

  5. Thread.join()方法

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B.t.join() ...

  6. hdu4087ALetter to Programmers(三维旋转矩阵)

    参考 三维旋转矩阵 + 矩阵加速 这个还要用到仿射变换. 平移 translate tx ty tz 1 0 0 tx 0 1 0 ty 0 0 1 tz 0 0 0 1 缩放 scale kx ky ...

  7. C语言程序设计进阶 第1周编程题

    第1周编程题 查看帮助 返回 依照学术诚信条款,我保证此作业是本人独立完成的. 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业截止时间之前不限次数 ...

  8. windows插件框架

    X3C,张云贵,http://blog.csdn.net/clever101/article/details/8656720

  9. ArcGIS发布服务时缓存切片设置

    [文件]>[共享]>[服务]>[覆盖原有服务]或[创建新服务] 设置好相关参数后,会弹出"服务编辑框": 进入"缓存" 1."绘制此 ...

  10. 20145224&20145238 《信息安全系统设计基础》 第四次实验

    20145224&20145238 <信息安全系统设计基础>第四次实验 课程:信息安全系统设计基础 班级:1452 姓名:陈颢文 荆玉茗 学号:20145224 20145238 ...