直接插入排序

过程:

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

for (j=i+1; 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

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

for(j=0,has_exchanged = 0; j

if(ar[j] > ar[j+1]){

tmp = ar[j+1];

ar[j+1] = ar[j];

ar[j] = tmp;

has_exchanged = 1;

}

}

}

}

偷张图:

算法面试用c还是python_排序算法(C语言+Python版)宝宝再也不怕面试官写排序算法了...相关推荐

  1. 国密算法Go语言实现(详解)(十) ——SM2(椭圆曲线公钥密码算法)

    国密算法Go语言实现(详解)(十) --SM2(椭圆曲线公钥密码算法) 原创代码:https://github.com/ZZMarquis/gm 引用时,请导入原创代码库.本文仅以注释方式详解代码逻辑 ...

  2. Interview:算法岗位面试—10.15上午—上海某公司算法岗位(偏图像算法,制造行业)技术面试考点之AI算法与实际场景结合产生商业价值的头脑风暴

    Interview:算法岗位面试-10.15上午-上海某公司算法岗位(偏图像算法,制造行业)技术面试考点之AI算法与实际场景结合产生商业价值的头脑风暴 导读:一心想去互联网,未必能够发挥自己最大价值, ...

  3. 国密算法Go语言实现(详解)(九) ——SM2(椭圆曲线公钥密码算法)

    国密算法Go语言实现(详解)(九) --SM2(椭圆曲线公钥密码算法) 原创代码:https://github.com/ZZMarquis/gm 引用时,请导入原创代码库.本文仅以注释方式详解代码逻辑 ...

  4. 蓝桥杯之算法模板题 Python版

    蓝桥杯之算法模板题 Python版 文章目录 蓝桥杯之算法模板题 Python版 线段树 DP 动态规划 dp, LIS ** 01背包 完全背包 多重背包 混合背包 分组背包 区间DP 一.什么是区 ...

  5. java python算法_用Python,Java和C ++示例解释的排序算法

    java python算法 什么是排序算法? (What is a Sorting Algorithm?) Sorting algorithms are a set of instructions t ...

  6. 排序算法总结(Python版)

    经典排序算法总结与实现 经典排序算法在面试中占有很大的比重,也是基础,为了未雨绸缪,这次收集整理并用Python实现了八大经典排序算法,包括冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序, ...

  7. “算法不行,干啥都不行!”面试官:面试基本都会考这点!

    无论你是 Java,Python,还是 PHP,面试总逃脱不了一个问题:算法! 据统计,各大厂笔试平均通过率只有 10%~20%,基本都折在了算法上. 滴滴出行笔试通过率为 18.2%: 腾讯秋招笔试 ...

  8. c++编写算法判断二叉树是否为完全二叉树_字节面试官:连这90道LeetCode算法题都不会也来面试?...

    面试大厂必刷:LeetCode算法90题 1. 买股票的最佳时机 难度级别:简单 题目: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一 ...

  9. java克鲁斯卡尔算法_Java语言基于无向有权图实现克鲁斯卡尔算法代码示例

    所谓有权图,就是图中的每一条边上都会有相应的一个或一组值.通常情况下,这个值只是一个数字 如:在交通运输网中,边上的权值可能表示的是路程,也可能表示的是运输费用(显然二者都是数字).不过,边上的权值也 ...

最新文章

  1. DV录像带导出一定要用1394
  2. 说说 Spring 事务管理的实现类
  3. 单链表的创建示意图, 显示单向链表的分析
  4. seci-log1.02日志分析软件版本升级了
  5. 软件工程--第六周学习进度
  6. ES6学习笔记(三):教你用js面向对象思维来实现 tab栏增删改查功能
  7. 【Java】springboot学习笔记二
  8. 基于Gsoap 的ONVIF C++ 库
  9. linux dd克隆系统后,Ubuntu14.04 dd命令克隆系统镜像安装到另一台机器上
  10. FileSaver、js-xlsx、SheetJS在线报表预览导出
  11. 数据分析告诉你,韦小宝跟他七个老婆哪个最亲?
  12. 地震matlab频域分析,MATLAB在地震数据分析中的应用
  13. android反编译apk命令,APK反编译关键命令及步骤
  14. 如何清除Excel2007中的网格线?
  15. 腾讯内部深度文章曝光:微信向左 手机QQ向右
  16. 多设备同步课程表,适用于iOS与Android
  17. MCScanX使用说明
  18. 关于VB.NET IIF函数
  19. 粗读MD-UNET: Multi-input dilated U-shape neural network for segmentation of bladder cancer
  20. esp8266编译固件问题 踏坑之旅

热门文章

  1. 安防IT化如何把握其中的共性与个性
  2. 基于ONVIF协议的(IPC)客户端程序开发-10 设备校时
  3. 客户管理系统CRM推荐
  4. 计算机制图笔记本需要什么配置,绘图笔记本需要什么配置?
  5. 移动CMPP3.0短信网关接口协议
  6. SQlite3基本用法,使用sublime编辑器
  7. Linux系统编程:IPC信号量
  8. 企业服务器固态硬盘寿命,SSD固态硬盘使用寿命短?_企业存储技术与评测-中关村在线...
  9. mysql字段的区分度_详解MySQL索引长度和区分度之间的平衡,值得收藏
  10. 如何用python画爱心型线_如何用python画爱心