直接插入排序

过程:
1. 数据可分看成两个部分,前面的数据是有序的
2. 从后面的数据取出一个元素,插到前面有序数据的合适位置
从右端开始查找,到找到比此元素大的时候,则此元素向后移动,以空出多余的空间来插入此元素。
3. 查找至最后。

例:
3 2 4 5 8 1
2 3 4 5 8 1
1 2 3 4 5 8

def insert_sort(lists):
count = len(lists) for i in range(1, count):
tmp = lists[i]
j = i - 1
while j >= 0 and lists[j]>tmp:
lists[j+1] = lists[j]
j -= 1 lists[j+1] = tmp
return lists
void direct_insert_sort(int *ar, int count);

void direct_insert_sort(int *ar, int count){
int tmp;
int i;
int j; for (i=1; i < count; i++){
tmp = ar[i];
j = i-1;
while(j>=0 && (ar[j] > tmp) ){
ar[j+1] = ar[j];
j--;
}
ar[j+1] = tmp;
}
}

  

希尔排序

过程:
1.将所有的数据分组为N/2;这样每组就有2个数据,利用直接插入排序。
2.将所有的数据分组为N/2*2; 每组就有4个数据,利用直接插入排序。
3.step大于等于1,最后再一次直接插入排序

评价:
1. 时间复杂度:n^1.25 或者 nlog2(n)
2. 非稳定
3. 插入排序对于“局部有序”有较好的表现

def shell_sort(lists):
count = len(lists)
step = count/2
while step>0:
for i in range(step, count, step):
tmp = lists[i]
j = i - step
while j >= 0 and lists[j] > tmp:
lists[j+step] = lists[j]
j -= step
lists[j+step] = tmp
step/=2
return lists

  

void inner_direct_insert_sort(int *ar, int count, int step);
void shell_sort(int *ar, int count); void shell_sort(int *ar, int count){
int step;
for (step=count/2; step > 0; step/=2)
inner_direct_insert_sort(ar, count, step);
} // 调用插入排序,但是这里需要改变步长。
void inner_direct_insert_sort(int *ar, int count, int step){
int tmp;
int i;
int j; for (i=step; i < count; i+=step){
tmp = ar[i];
j = i-step;
while(j>=0 && (ar[j] > tmp) ){
ar[j+step] = ar[j];
j-=step;
}
ar[j+step] = tmp;
}
}

冒泡排序:

哈哈最简单了

1. 从头开始,依次和自己后面的元素进行比较,交换

时间复杂度也很高O(N^2)

def bubble_sort(lists):
count = len(lists)
for i in range(0, count):
for j in range(i+1, count)
if lists[i] > lists[j]:
lists[i], lists[j] = lists[j], lists[i]
return lists

  

void bubble_sort(int *ar, int count);

void bubble_sort(int *ar, int count){
int i;
int j;
int tmp; for(i=0; i<count; i++){
for (j=i+1; j<count; j++){
if(ar[i] > ar[j]){
tmp = ar[i];
ar[i] = ar[j];
ar[j] = tmp;
}
}
}
}

  

快速排序

过程:
1、基本的步骤
首先确定参考元素,参考元素左边是比参考元素小的元素,参考元素右边是比参考元素大的元素;
即参考元素把数据分成两部分
先设参考

2、递归调用基本的步骤

评价:
时间复杂度:O(N*log2N)
稳定性:非稳定
如果第一个参考元素比后面的有多个元素大,则排序之后逆序
如果第一个参考元素比后面的有多个元素小,则排序之后顺序

最差情况:完全逆序、完全顺序

def quick_sort(lists, left, right):
if left >= right:
return lists tmp = lists[left]
start = left
end = right while left < right:
while left < right and lists[right] > tmp:
right -= 1
if left < right:
lists[left] = lists[right]
left += 1 while left < right and lists[left] < tmp:
left += 1
if left < right:
lists[right] = lists[left]
right -= 1
lists[left] = tmp quick_sort(lists, start, left-1)
quick_sort(lists, left+1, end)
return lists

  

int base_action(int *ar, int start_index, int end_index);
void inner_quick_sort(int *ar, int start_index, int end_index);
void quick_sort(int *ar, int count); void quick_sort(int *ar, int count){
inner_quick_sort(ar, 0, count-1);
} void inner_quick_sort(int *ar, int start_index, int end_index){
int mid_index; if(start_index < end_index){
mid_index = base_action(ar, start_index, end_index);
inner_quick_sort(ar, start_index, mid_index-1);
inner_quick_sort(ar, mid_index+1, end_index);
}
} int base_action(int *ar, int start_index, int end_index){
int tmp; tmp = ar[start_index];
while(start_index < end_index){
while(start_index < end_index && ar[end_index] > tmp){
end_index--;
} if(start_index < end_index){
ar[start_index] = ar[end_index];
start_index++;
} while(start_index < end_index && ar[start_index] < tmp){
start_index++;
} if(start_index < end_index){
ar[end_index] = ar[start_index];
end_index--;
}
}
ar[start_index] = tmp; return start_index;
}

  

直接选择排序

过程:
1. 先在所有的元素中选出最值,则当前的第一个元素交换,即放到有序的集合里面;
2. 再在后面剩余的元素中找出最值,放到之前的有序集合里面。注意,是放在有序集合的最右边;
2.1 选取下一个节点为参考元素,接着和剩余的元素作比较,选出最值的下标。
2.2 循环完成,就选择出了最值了。
2.3 检测最值的下标和之前的参考元素的下标是否相同,如果相同的话,说明中间并没有改变,
也就是说参考元素就是最值。
如果最值的下标和之前的参考元素的下标不同,则交换元素。

评价:
1. 时间复杂度:O( (1+n-1)n/2) ==>O(n*n)
2. 非稳定的
3. 完全升序,交换次数最少
4. 完全逆序,交换次数不是最多;

def select_sort(lists):
count = len(lists) for i in range(count):
min_index = i
for j in range(i+1,count):
if lists[j] < lists[min_index]:
min_index = j
if min_index != i:
lists[i], lists[min_index] = lists[min_index], lists[i]
return lists

  

void direct_select_sort(int *ar, int count);

void direct_select_sort(int *ar, int count){
int tmp; //用于交换的中间值
int i; //下一个要比较的元素,即参考元素
int j; //除了已排好序的集合和下一个元素,剩下的所有元素的都和下一个元素比较
int minIndex;      //最小的值的下标,将来放到已排好的元素中去 for (i=0; i < count-1; i++){
minIndex = i;
for (j = i+1; j<count; j++){
if(ar[j] < ar[minIndex] ){
minIndex = j;
}
}
if (minIndex != i){
tmp = ar[minIndex];
ar[minIndex] = ar[i];
ar[i] = tmp;
}
}
}

  

堆排序

过程:
1、将整个的数据,调整成大根堆。(大根堆:根节点大于左右节点,调整过程深度优先)
这里提下完全二叉树的性质
设总结点为count
叶子节点数量:(count+1)/2
非叶子节点数量: count - (count+1)/2 = (count-1)/2
最后一个非节点: (count-1)/2 - 1
2、将根节点和最后一个叶子节点交换。之后再次调整整棵数为大根堆
3、直到只有一个根节点

评价:
1. 非稳定
2. O(N·log2N)
3. 完全顺序:小跟堆,最差情况
4. 完全逆序:大根堆,比较次数不变。最优情况

def adjust_head(lists, root, count):
not_finished = True while not_finished and root <= (count-1)/2:
max_index = root
left_child = 2*root + 1
right_child = 2*root + 2
if left_child < count and lists[left_child] > lists[max_index]:
max_index = left_child
if right_child < count and lists[right_child] > lists[max_index]:
max_index = right_child
if root != max_index:
lists[root], lists[max_index] = lists[max_index], lists[root]
else:
not_finished = False
root = max_index def heap_sort(lists):
count = len(lists)
last_not_leaf_node = (count-1)/2
for root in range(last_not_leaf_node, -1, -1):
adjust_head(lists, root,count) #调整为大跟堆
while count > 1:
lists[count-1], lists[0] = lists[0], lists[count-1]
count -= 1
adjust_head(lists,root, count)
return lists

  

void adjustBigHeap(int *ar, int count, int root);
void heapSort(int *ar, int count); void heapSort(int *ar, int count){
int root;
int tmp; for(root = (count-1)/2-1; root > 0; root--){
adjustBigHeap(ar, count, root);
} while(count > 1){
adjustBigHeap(ar, count, root);
tmp = ar[0];
ar[0] = ar[count-1];
ar[count-1] = tmp;
count--;
}
} void adjustBigHeap(int *ar, int count, int root){
int maxIndex;
int tmp;
boolean finished = FALSE; while(!finished && maxIndex < (count-1)/2){
maxIndex = 2*root+1 < count && ar[2*root+1] > ar[root] ? 2*root+1 : root;
maxIndex = 2*root+2 < count && ar[2*root+2] > ar[maxIndex] ? 2*root+2 : maxIndex; if(maxIndex != root){
tmp = ar[root];
ar[root] = ar[maxIndex];
ar[maxIndex] = tmp;
}else{
finished = TRUE;
}
root = maxIndex;
}
}

归并算法:分而治之

1. 将所有的数一分为二,在把其中的一组再一分为二,如此反复,最后在将有序的数组合并

2. 最关键的就是,递归终止的条件,即当每个组中只有一个元素。

3. 最重要的就是处理怎么合并。假设左边有序的起点为i, 右边有序的起点为j。将左右两边的数组相互比较,如果左边小的话,将比较的元素放入到结果集中,同时i应该加1。

 如果右边元素大,则它放到结果集中,同时j要加1。如果左右两边其中的一边达到顶端(mid/end),则把另一组元素全部放到结果集中

评价:

平均情况   最坏情况     最好情况     空间复杂度
O(nlog2n)  O(nlog2n)     O(nlog2n)   O(n)
稳定

def merge(left, right):
i, j = 0, 0
rst = []
while i < len(left) and j < len(right):
if left[i] <= right[j]:
rst.append(left[i])
i += 1
else:
rst.append(right[j])
j += 1
rst += left[i:]
rst += right[j:] return rst def merge_sort(lists):
if len(lists) <= 1:
return lists middle = len(lists)/2
left = merge_sort(lists[middle:])
right = merge_sort(lists[:middle]) return merge(left, right)
void merge_sort(int *ar, int left, int right);
void merge(int *ar, int left, int right); void merge_sort(int *ar, int left, int right){
int i;
if(left < right){
i = (left + right)/2;
merge_sort(a, left, i);
merge_sort(a, i+1, right);
merge(a, left, right);
}
} void merge(int *ar, int left, int right){
int begin1 = left;
int mid = (left + right)/2;
int begin2 = mid+1;
int k = 0;
int new_ar_len = right - left + 1;
int *b = (int *)malloc(new_ar_len*sizeof(int));
while(begin1 <= mid && begin2 <= right){
if(ar[begin1] <= ar[begin2]){
b[k++] = ar[begin1++];
}else {
b[k++] = ar[begin2++];
}
while(begin1 <= mid)
b[k++] = ar[begin1++];
while(begin2 <= right)
b[k++] = ar[begin2++];
copy_array(b, a, new_ar_len, left);
free(b);
}
} void copy_array(int *src, int *dst, int new_ar_len, int first){
int i;
int j=first; for(i=0; i < len; i++){
dst[j] = src[i];
j++;
}
}

基数排序:

将所有的数,按照各位进行排序并保持数组,接着按照十位排序,进行百位...

桶的个数,应该是基数的大小

进行比较的次数=所有元素最大数所占的位数

def radix_sort(lists):
for k in xrange(len(str(max(lists)))):
bucket = [ [] for _ in xrange(10)]
for i in lists:
bucket[i / (10 ** k) % 10].append(i)
lists = [element for item in bucket for element in item]
return lists

  c语言我看着晕~

直接交换排序

过程:
相邻的两个比较,交换;
一轮比较之后,最后的一个数为最值(比较时使用'>',为升序,最后一个为最大值)
下一比较,那么最后的数值就不需要比较。如m次比较,只需比较前面1,n-m-1之间的数
但是如果在一次比较的过程中,没有交换数据,那么数值就已经排序完成了。这里借助了标志位来判断

时间复杂度:O(n^2)
稳定!
最优:全为升序
最差:全为逆序

  

def exchange_sort(lists):
count = len(lists)
has_exchanged = True           #在比较的过程中,如果没有数字发生交换,那么说明数据已经有序的了。退出即可 for i in range(0, count):
for j in range(0, count-i-1):
has_exchanged = False
if lists[j] > lists[j+1]:
lists[j], lists[j+1] = lists[j+1], lists[j]
has_exchanged = True
if not has_exchanged:
break return lists

  

void direct_change_sort(int *ar, int count){
int i;
int j;
int tmp;
unsigned char has_exchanged; for(i=0; i<count && has_exchanged ; i++){
for(j=0,has_exchanged = 0; j<count-i; j++){
if(ar[j] > ar[j+1]){
tmp = ar[j+1];
ar[j+1] = ar[j];
ar[j] = tmp;
has_exchanged = 1;
}
}
}
}

  

偷张图:

排序算法(C语言+Python版)宝宝再也不怕面试官写排序算法了的更多相关文章

  1. 算法(第4版)-1.5 案例研究:union-find算法

    问题→ 动态连通性:当程序从输入中读取了整数对p q时,如果已知的所有整数对都不能说明p和q是相连的,那么则将这一对整数写入到输出中.如果已知的数据可以说明p和q 是相连的,那么程序应该忽略p q这对 ...

  2. 数论基础算法总结(python版)

    /* Author: wsnpyo Update Date: 2014-11-16 Algorithm: 快速幂/Fermat, Solovay_Stassen, Miller-Rabin素性检验/E ...

  3. Springboot启动扩展点超详细总结,再也不怕面试官问了

    1.背景 Spring的核心思想就是容器,当容器refresh的时候,外部看上去风平浪静,其实内部则是一片惊涛骇浪,汪洋一片.Springboot更是封装了Spring,遵循约定大于配置,加上自动装配 ...

  4. 深度剖析Java的volatile实现原理,再也不怕面试官问了

    上篇文章我们讲了synchronized的用法和实现原理,我们总爱说synchronized是重量级锁,volatile是轻量级锁.为什么volatile是轻量级锁,体现在哪些方面?以及volatil ...

  5. 图解Java线程的生命周期,看完再也不怕面试官问了

    文章首发自个人微信公众号: 小哈学Java https://www.exception.site/java-concurrency/java-concurrency-thread-life-cycle ...

  6. 看完这一篇,再也不怕面试官问到IntentService的原理

    IntentService是什么 在内部封装了 Handler.消息队列的一个Service子类,适合在后台执行一系列串行依次执行的耗时异步任务,方便了我们的日常coding(普通的Service则是 ...

  7. 手写webpack核心原理,再也不怕面试官问我webpack原理

    手写webpack核心原理 目录 手写webpack核心原理 一.核心打包原理 1.1 打包的主要流程如下 1.2 具体细节 二.基本准备工作 三.获取模块内容 四.分析模块 五.收集依赖 六.ES6 ...

  8. 算法(第四版)C#题解——2.1

    算法(第四版)C#题解——2.1   写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csh ...

  9. 人脸验证算法Joint Bayesian详解及实现(Python版)

    人脸验证算法Joint Bayesian详解及实现(Python版) Tags: JointBayesian DeepLearning Python 本博客仅为作者记录笔记之用,不免有很多细节不对之处 ...

随机推荐

  1. hadoop运行测试命令遇到的问题

    2017-02-16 09:46:14,926 INFO mapreduce.Job: Task Id : attempt_1487148856575_0001_m_000001_0, Status ...

  2. BZOJ 1620 [Usaco2008 Nov]Time Management 时间管理:贪心

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1620 题意: 有n个工作,每一个工作完成需要花费的时间为tim[i],完成这项工作的截止日 ...

  3. 记录ubuntu16.04版本安装过程中遇到的问题

    记录ubuntu16.04版本安装和使用过程中遇到的些问题,方便以后查看,主要内容有: 1. ubuntu源替换 2. windows与vmware ubuntu文件夹共享 3. putty连接ubu ...

  4. 截图工具,更改系统默认快捷键,系统配置实用程序,以管理员身份运行cmd(win7)

    截图工具: 开始--附件--右键发送到桌面快捷方式---桌面截图工具右键属性--快捷方式 更改系统默认快捷键: 控制面板--外观和个性化--调整屏幕分辨率--高级设置---英特尔图形和媒体控制面板-- ...

  5. npm --- Node.js包管理器

    目录 1. 安装Node.js 2. 运行npm 3. npm介绍 3.1 安装插件 3.2 更新插件 3.3 卸载插件 3.4 查看当前目录中的插件列表 4. 使用cnpm 4.1 安装 npm( ...

  6. Mutual information and Normalized Mutual information 互信息和标准化互信息

    实验室最近用到nmi( Normalized Mutual information )评价聚类效果,在网上找了一下这个算法的实现,发现满意的不多. 浙江大学蔡登教授有一个,http://www.zju ...

  7. 利用openssl进行base64的编码与解码

    openssl可以直接使用命令对文件件进行base64的编码与解码,利用openssl提供的API同样可以做到这一点. 废话不多说,直接上代码了.需要注意的是通过base64编码后的字符每64个字节都 ...

  8. Spark Streaming之三:DStream解析

    DStream 1.1基本说明 1.1.1 Duration Spark Streaming的时间类型,单位是毫秒: 生成方式如下: 1)new Duration(milli seconds) 输入毫 ...

  9. EasyUI 下载与引用

    1.官网下载地址: http://www.jeasyui.com/download/index.php 一般下载 “GPL Edition” (开源版本). 2.目录结构: demo:案例,可以删 l ...

  10. Struts文件上传下载

    Struts配置文件: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PU ...