直接插入排序

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

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

  1. def insert_sort(lists):
  2. count = len(lists)
  3.  
  4. for i in range(1, count):
  5. tmp = lists[i]
  6. j = i - 1
  7. while j >= 0 and lists[j]>tmp:
  8. lists[j+1] = lists[j]
  9. j -= 1
  10.  
  11. lists[j+1] = tmp
  12. return lists
  1. void direct_insert_sort(int *ar, int count);
  2.  
  3. void direct_insert_sort(int *ar, int count){
  4. int tmp;
  5. int i;
  6. int j;
  7.  
  8. for (i=1; i < count; i++){
  9. tmp = ar[i];
  10. j = i-1;
  11. while(j>=0 && (ar[j] > tmp) ){
  12. ar[j+1] = ar[j];
  13. j--;
  14. }
  15. ar[j+1] = tmp;
  16. }
  17. }

  

希尔排序

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

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

  1. def shell_sort(lists):
  2. count = len(lists)
  3. step = count/2
  4. while step>0:
  5. for i in range(step, count, step):
  6. tmp = lists[i]
  7. j = i - step
  8. while j >= 0 and lists[j] > tmp:
  9. lists[j+step] = lists[j]
  10. j -= step
  11. lists[j+step] = tmp
  12. step/=2
  13. return lists

  

  1. void inner_direct_insert_sort(int *ar, int count, int step);
  2. void shell_sort(int *ar, int count);
  3.  
  4. void shell_sort(int *ar, int count){
  5. int step;
  6. for (step=count/2; step > 0; step/=2)
  7. inner_direct_insert_sort(ar, count, step);
  8. }
  9.  
  10. // 调用插入排序,但是这里需要改变步长。
  11. void inner_direct_insert_sort(int *ar, int count, int step){
  12. int tmp;
  13. int i;
  14. int j;
  15.  
  16. for (i=step; i < count; i+=step){
  17. tmp = ar[i];
  18. j = i-step;
  19. while(j>=0 && (ar[j] > tmp) ){
  20. ar[j+step] = ar[j];
  21. j-=step;
  22. }
  23. ar[j+step] = tmp;
  24. }
  25. }

冒泡排序:

哈哈最简单了

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

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

  1. def bubble_sort(lists):
  2. count = len(lists)
  3. for i in range(0, count):
  4. for j in range(i+1, count)
  5. if lists[i] > lists[j]:
  6. lists[i], lists[j] = lists[j], lists[i]
  7. return lists

  

  1. void bubble_sort(int *ar, int count);
  2.  
  3. void bubble_sort(int *ar, int count){
  4. int i;
  5. int j;
  6. int tmp;
  7.  
  8. for(i=0; i<count; i++){
  9. for (j=i+1; j<count; j++){
  10. if(ar[i] > ar[j]){
  11. tmp = ar[i];
  12. ar[i] = ar[j];
  13. ar[j] = tmp;
  14. }
  15. }
  16. }
  17. }

  

快速排序

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

2、递归调用基本的步骤

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

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

  1. def quick_sort(lists, left, right):
  2. if left >= right:
  3. return lists
  4.  
  5. tmp = lists[left]
  6. start = left
  7. end = right
  8.  
  9. while left < right:
  10. while left < right and lists[right] > tmp:
  11. right -= 1
  12. if left < right:
  13. lists[left] = lists[right]
  14. left += 1
  15.  
  16. while left < right and lists[left] < tmp:
  17. left += 1
  18. if left < right:
  19. lists[right] = lists[left]
  20. right -= 1
  21. lists[left] = tmp
  22.  
  23. quick_sort(lists, start, left-1)
  24. quick_sort(lists, left+1, end)
  25. return lists

  

  1. int base_action(int *ar, int start_index, int end_index);
  2. void inner_quick_sort(int *ar, int start_index, int end_index);
  3. void quick_sort(int *ar, int count);
  4.  
  5. void quick_sort(int *ar, int count){
  6. inner_quick_sort(ar, 0, count-1);
  7. }
  8.  
  9. void inner_quick_sort(int *ar, int start_index, int end_index){
  10. int mid_index;
  11.  
  12. if(start_index < end_index){
  13. mid_index = base_action(ar, start_index, end_index);
  14. inner_quick_sort(ar, start_index, mid_index-1);
  15. inner_quick_sort(ar, mid_index+1, end_index);
  16. }
  17. }
  18.  
  19. int base_action(int *ar, int start_index, int end_index){
  20. int tmp;
  21.  
  22. tmp = ar[start_index];
  23. while(start_index < end_index){
  24. while(start_index < end_index && ar[end_index] > tmp){
  25. end_index--;
  26. }
  27.  
  28. if(start_index < end_index){
  29. ar[start_index] = ar[end_index];
  30. start_index++;
  31. }
  32.  
  33. while(start_index < end_index && ar[start_index] < tmp){
  34. start_index++;
  35. }
  36.  
  37. if(start_index < end_index){
  38. ar[end_index] = ar[start_index];
  39. end_index--;
  40. }
  41. }
  42. ar[start_index] = tmp;
  43.  
  44. return start_index;
  45. }

  

直接选择排序

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

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

  1. def select_sort(lists):
  2. count = len(lists)
  3.  
  4. for i in range(count):
  5. min_index = i
  6. for j in range(i+1,count):
  7. if lists[j] < lists[min_index]:
  8. min_index = j
  9. if min_index != i:
  10. lists[i], lists[min_index] = lists[min_index], lists[i]
  11. return lists

  

  1. void direct_select_sort(int *ar, int count);
  2.  
  3. void direct_select_sort(int *ar, int count){
  4. int tmp; //用于交换的中间值
  5. int i; //下一个要比较的元素,即参考元素
  6. int j; //除了已排好序的集合和下一个元素,剩下的所有元素的都和下一个元素比较
  7. int minIndex;      //最小的值的下标,将来放到已排好的元素中去
  8.  
  9. for (i=0; i < count-1; i++){
  10. minIndex = i;
  11. for (j = i+1; j<count; j++){
  12. if(ar[j] < ar[minIndex] ){
  13. minIndex = j;
  14. }
  15. }
  16. if (minIndex != i){
  17. tmp = ar[minIndex];
  18. ar[minIndex] = ar[i];
  19. ar[i] = tmp;
  20. }
  21. }
  22. }

  

堆排序

过程:
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. 完全逆序:大根堆,比较次数不变。最优情况

  1. def adjust_head(lists, root, count):
  2. not_finished = True
  3.  
  4. while not_finished and root <= (count-1)/2:
  5. max_index = root
  6. left_child = 2*root + 1
  7. right_child = 2*root + 2
  8. if left_child < count and lists[left_child] > lists[max_index]:
  9. max_index = left_child
  10. if right_child < count and lists[right_child] > lists[max_index]:
  11. max_index = right_child
  12. if root != max_index:
  13. lists[root], lists[max_index] = lists[max_index], lists[root]
  14. else:
  15. not_finished = False
  16. root = max_index
  17.  
  18. def heap_sort(lists):
  19. count = len(lists)
  20. last_not_leaf_node = (count-1)/2
  21. for root in range(last_not_leaf_node, -1, -1):
  22. adjust_head(lists, root,count) #调整为大跟堆
  23. while count > 1:
  24. lists[count-1], lists[0] = lists[0], lists[count-1]
  25. count -= 1
  26. adjust_head(lists,root, count)
  27. return lists

  

  1. void adjustBigHeap(int *ar, int count, int root);
  2. void heapSort(int *ar, int count);
  3.  
  4. void heapSort(int *ar, int count){
  5. int root;
  6. int tmp;
  7.  
  8. for(root = (count-1)/2-1; root > 0; root--){
  9. adjustBigHeap(ar, count, root);
  10. }
  11.  
  12. while(count > 1){
  13. adjustBigHeap(ar, count, root);
  14. tmp = ar[0];
  15. ar[0] = ar[count-1];
  16. ar[count-1] = tmp;
  17. count--;
  18. }
  19. }
  20.  
  21. void adjustBigHeap(int *ar, int count, int root){
  22. int maxIndex;
  23. int tmp;
  24. boolean finished = FALSE;
  25.  
  26. while(!finished && maxIndex < (count-1)/2){
  27. maxIndex = 2*root+1 < count && ar[2*root+1] > ar[root] ? 2*root+1 : root;
  28. maxIndex = 2*root+2 < count && ar[2*root+2] > ar[maxIndex] ? 2*root+2 : maxIndex;
  29.  
  30. if(maxIndex != root){
  31. tmp = ar[root];
  32. ar[root] = ar[maxIndex];
  33. ar[maxIndex] = tmp;
  34. }else{
  35. finished = TRUE;
  36. }
  37. root = maxIndex;
  38. }
  39. }

归并算法:分而治之

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

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

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

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

评价:

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

  1. def merge(left, right):
  2. i, j = 0, 0
  3. rst = []
  4. while i < len(left) and j < len(right):
  5. if left[i] <= right[j]:
  6. rst.append(left[i])
  7. i += 1
  8. else:
  9. rst.append(right[j])
  10. j += 1
  11. rst += left[i:]
  12. rst += right[j:]
  13.  
  14. return rst
  15.  
  16. def merge_sort(lists):
  17. if len(lists) <= 1:
  18. return lists
  19.  
  20. middle = len(lists)/2
  21. left = merge_sort(lists[middle:])
  22. right = merge_sort(lists[:middle])
  23.  
  24. return merge(left, right)
  1. void merge_sort(int *ar, int left, int right);
  2. void merge(int *ar, int left, int right);
  3.  
  4. void merge_sort(int *ar, int left, int right){
  5. int i;
  6. if(left < right){
  7. i = (left + right)/2;
  8. merge_sort(a, left, i);
  9. merge_sort(a, i+1, right);
  10. merge(a, left, right);
  11. }
  12. }
  13.  
  14. void merge(int *ar, int left, int right){
  15. int begin1 = left;
  16. int mid = (left + right)/2;
  17. int begin2 = mid+1;
  18. int k = 0;
  19. int new_ar_len = right - left + 1;
  20. int *b = (int *)malloc(new_ar_len*sizeof(int));
  21. while(begin1 <= mid && begin2 <= right){
  22. if(ar[begin1] <= ar[begin2]){
  23. b[k++] = ar[begin1++];
  24. }else {
  25. b[k++] = ar[begin2++];
  26. }
  27. while(begin1 <= mid)
  28. b[k++] = ar[begin1++];
  29. while(begin2 <= right)
  30. b[k++] = ar[begin2++];
  31. copy_array(b, a, new_ar_len, left);
  32. free(b);
  33. }
  34. }
  35.  
  36. void copy_array(int *src, int *dst, int new_ar_len, int first){
  37. int i;
  38. int j=first;
  39.  
  40. for(i=0; i < len; i++){
  41. dst[j] = src[i];
  42. j++;
  43. }
  44. }

基数排序:

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

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

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

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

  c语言我看着晕~

直接交换排序

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

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

  

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

  

  1. void direct_change_sort(int *ar, int count){
  2. int i;
  3. int j;
  4. int tmp;
  5. unsigned char has_exchanged;
  6.  
  7. for(i=0; i<count && has_exchanged ; i++){
  8. for(j=0,has_exchanged = 0; j<count-i; j++){
  9. if(ar[j] > ar[j+1]){
  10. tmp = ar[j+1];
  11. ar[j+1] = ar[j];
  12. ar[j] = tmp;
  13. has_exchanged = 1;
  14. }
  15. }
  16. }
  17. }

  

偷张图:

排序算法(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. python把字典写入excel之一例

    直接上代码: # -*- coding: utf-8 -*- import xlsxwriter #生成excel文件 def generate_excel(expenses): workbook = ...

  2. js跳转方式 【转】

    第一种:    <script language="javascript" type="text/javascript">           wi ...

  3. BZOJ_5416_[Noi2018]冒泡排序_DP+组合数+树状数组

    BZOJ_5416_[Noi2018]冒泡排序_DP+组合数+树状数组 Description www.lydsy.com/JudgeOnline/upload/noi2018day1.pdf 好题. ...

  4. linux下实现目录即文件的完整删除

    功能: 1.删除目录 2.删除文件 3.删除不为空的目录即下属文件 #ifndef _DELETE_FILE #define _DELETE_FILE #include <sys/stat.h& ...

  5. bzoj 3481 DZY Loves Math III——反演+rho分解质因数

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3481 推推式子发现:令Q=gcd(P,Q),ans=Σ(d|Q) d*phi(P/d).把 ...

  6. selenium_page_object

    最简单的pageobject github地址:https://github.com/defnngj/selenium_page_objects

  7. jquery data 选择器 表格序列化serialize()

    data()在元素上存放或者读取数据,返回jquery对象. demo: <div data-obj="{'name':'zhangsan','age':20}">&l ...

  8. 【原】Cache Buffer Chain 第四篇

    作者:david_zhang@sh [转载时请以超链接形式标明文章] 链接:http://www.cnblogs.com/david-zhang-index/p/3873357.html [测试1]低 ...

  9. PICO SCOPE 3000 Series 示波器

  10. 2 pyspark学习----基本操作

    1 spark的python环境部署可以参照上面一篇哟.http://www.cnblogs.com/lanjianhappy/p/8705974.html 2 pyspark的基本操作. # cod ...