临近毕业季,在跳蚤市场收了一本**《啊哈!算法》**,我之前是没有学过算法的,之间就知道这本书的存在,所以看见了它,就毫不犹豫地买它!!!一边看一边写写博客,保留一下自己的学习历程ovo!
此篇文章字数有点长,请谨慎观看

第1章、一大波数正在靠近——排序

第一节 最快最简单的排序——桶排序(简化版)

适用于数少,且连续的整数排序,出现一个数字i就将数组的i号元素加1,最后i号元素的值就是i出现的次数,从大到小输出,从小到大输出都可以。

#include <stdio.h>
int main()
{ int a[11],i,j,t; for(i=0;i<=10;i++) a[i]=0; //初始化为0 for(i=1;i<=5;i++) //循环读入5个数{ scanf("%d",&t); //把每一个数读到变量t中a[t]++; //进行计数} for(i=0;i<=10;i++) //依次判断a[0]~a[10] for(j=1;j<=a[i];j++) //出现了几次就打印几次printf("%d ",i); getchar();getchar(); //这里的getchar();用来暂停程序,以便查看程序输出的内容//也可以用system("pause");等来代替return 0;
}

每一个桶的作用就是“标记”每个数出现的次数。

该算法的时间复杂度是 O(m+n+m+n),即 O(2*(m+n))。我们在说时间复杂度的时候可以忽略较小的常数,最终桶排序的时间复杂度为O(m+n)。还有一点,在表示时间复杂度的时候,n 和 m通常用大写字母即 O(M+N)M为桶的个数,N为待排序的个数。
这是一个非常快的排序算法。

桶排序从 1956 年就开始被使用,该算法的基本思想是由E.J.Issac 和 R.C.Singleton
提出来的。之前我说过,其实这并不是真正的桶排序算法,真正的桶排序算法要比这个更加复杂。

如果要排序的数还对应一个名字,数从高到低排序,并且输出他们的名字。数使用桶排序后,怎样把名字对应输出呢?
这个问题可以用C语言的结构体或者Java的类来实现。
优点:非常快
缺点:排序数的范围大时浪费空间,不方便为小数排序

第二节 邻居好说话——冒泡排序

冒泡排序的基本思想是:每次比较两个相邻的元素,如果他们的顺序错误就把它们交换过来。
(1)遍历原始数据,从第一个数开始,到倒数第二个数结束,比较这个数和下一个数的大小,如果这个数比下一个数大,则交换这两个数。这样便可以将数据中最大的数转移到数组的最后。
(2)之后再次遍历原始数据,但是变为从第一个数开始,到倒数第三个数结束,比较这个数和下一个数的大小,如果这个数比下一个数大,则交换这两个数。这样便可以将第二大的数转移到数组的倒数第二位。
(3)重复执行上述过程,一直到从第一个数开始,到第二个数结束,从而完成了排序过程。
由于这个循环过程就像泡泡上浮的过程,所以被称为冒泡排序法。

#include <stdio.h>
int main()
{ int a[100],i,j,t,n; scanf("%d",&n); //输入一个数n,表示接下来有n个数for(i=1;i<=n;i++) //循环读入n个数到数组a中scanf("%d",&a[i]); //冒泡排序的核心部分for(i=1;i<=n-1;i++) //n个数排序,只用进行n-1趟{ for(j=1;j<=n-i;j++) //从第1位开始比较直到最后一个尚未归位的数,想一想为什么到n-i就可以了。{ if(a[j]<a[j+1]) //比较大小并交换{ t=a[j]; a[j]=a[j+1]; a[j+1]=t; } } } for(i=1;i<=n;i++) //输出结果printf("%d ",a[i]); getchar();getchar(); return 0;
}

冒泡排序的核心部分是双重嵌套循环。冒泡排序的时间复杂度是 O(N²)。这是一个非常高的时间复杂度。冒泡排序早在 1956
年就有人开始研究,之后有很多人都尝试过对冒泡排序进行改进,但结果却令人失望。如 Donald E. Knuth(中文名为高德纳,1974
年图灵奖获得者)所说:“冒泡排序除了它迷人的名字和导致了某些有趣的理论问题这一事实之外,似乎没有什么值得推荐的。"

第三节 最常用的排序——快速排序

(1)从数列中挑出一个元素,称为 “基准”(pivot);
(2)重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
(3)递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用 void quicksort(int left,int right)
{ int i,j,t,temp; if(left>right) return; temp=a[left]; //temp中存的就是基准数 i=left; j=right; while(i!=j) { //顺序很重要,要先从右往左找 while(a[j]>=temp && i<j) j--; //再从左往右找 while(a[i]<=temp && i<j) i++; //交换两个数在数组中的位置 if(i<j)//当哨兵i和哨兵j没有相遇时{ t=a[i]; a[i]=a[j]; a[j]=t; } } //最终将基准数归位 a[left]=a[i]; a[i]=temp; quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程 quicksort(i+1,right);//继续处理右边的,这里是一个递归的过程 return;
} int main() { int i,j,t; //读入数据 scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); quicksort(1,n); //快速排序调用 //输出排序后的结果 for(i=1;i<=n;i++) printf("%d ",a[i]); getchar();getchar(); return 0; }

快速排序由 C. A. R. Hoare(东尼·霍尔,Charles Antony Richard Hoare)在 1960年提出,之后又有许多人做了进一步的优化。如果你对快速排序感兴趣,可以去看看东尼·霍尔1962 年在 Computer Journal发表的论文“Quicksort”以及《算法导论》的第七章。

第四节 小哼买书

这一节讲的主要是去重排序,以n个正整数为例,进行去重排序。
解决这个问题的方法大致有两种。第一种方法:先将这 n 个整数去重,再进行从小到大排序并输出;第二种方法:先从小到大排序,输出的时候再去重。这两种方法都可以。
(1)先来看第一种方法。桶排序稍加改动正好可以起到去重的效果:

#include <stdio.h>
int main()
{ int a[1001],n,i,t; for(i=1;i<=1000;i++) a[i]=0; //初始化scanf("%d",&n); //读入n for(i=1;i<=n;i++) //循环读入n个整数{ scanf("%d",&t); //把每一个整数读到变量t中a[t]=1; //标记出现过的整数} for(i=1;i<=1000;i++) //依次判断1~1000这个1000个桶{ if(a[i]==1)//如果这个ISBN号出现过则打印出来printf("%d ",i); } getchar();getchar(); return 0;
}

这种方法的时间复杂度就是桶排序的时间复杂度:O(N+M);M为桶的个数,N为待排序的个数。
(2)第二种方法我们需要先排序再去重。排序我们可以用冒泡排序或者快速排序。
先排序,相同的数都会紧挨在一起。只要在输出的时候,预先判断一下当前这个数 a[i]与前面一个数 a[i-1]是否相同。如果相同则表示这个数之前已经输出过了,不用再次输出;不同则表示这个数是第一次出现,需要输出这个数。

#include <stdio.h>
int main()
{ int a[101],n,i,j,t; scanf("%d",&n); //读入n for(i=1;i<=n;i++) //循环读入n个图书ISBN号{ scanf("%d",&a[i]); } //开始冒泡排序for(i=1;i<=n-1;i++) { for(j=1;j<=n-i;j++) { if(a[j]>a[j+1]) { t=a[j]; a[j]=a[j+1]; a[j+1]=t; } } } printf("%d ",a[1]); //输出第1个数for(i=2;i<=n;i++) //从2循环到n { if( a[i] != a[i-1] ) //如果当前这个数是第一次出现则输出printf("%d ",a[i]); }getchar();getchar(); return 0;
}

这种方法的时间复杂度由两部分组成,一部分是冒泡排序的时间复杂度,是 O(N²),另一部分是读入和输出,都是 O(N),因此整个算法的时间复杂度是 O(2N+N²)。相对于 N²来说,2N 可以忽略(我们通常忽略低阶),最终该方法的时间复杂度是 O(N²)。

以上三种排序算法的时间复杂度。桶排序是最快的,它的时间复杂度是O(N+M);冒泡排序是 O(N²);快速排序是O(NlogN)。
谢谢你的坚持阅读ovo哟,让我们一起加油吖

《啊哈!算法》笔记_Day01相关推荐

  1. 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...

    来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...

  2. 数据结构与算法笔记 - 绪论

    数据结构与算法笔记 - 绪论 1. 什么是计算 2. 评判DSA优劣的参照(直尺) 3. 度量DSA性能的尺度(刻度) 4. DSA的性能度量的方法 5. DSA性能的设计及其优化 x1. 理论模型与 ...

  3. 数据结构与算法笔记(十六)—— 二叉搜索树

    一.二叉搜索树定义 二叉搜索树(Binary Search Tree),又名二叉排序树(Binary Sort Tree). 二叉搜索树是具有有以下性质的二叉树: 若左子树不为空,则左子树上所有节点的 ...

  4. 数据结构与算法笔记(十五)—— 散列(哈希表)

    一.前沿 1.1.直接寻址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术.假设某应用要用到一个动态集合,其中每个元素都有一个取自全域U={0,1,-,m-1)的关键字,此处m是一个不很大 ...

  5. 《algorithm-note》算法笔记中文版正式发布!

    无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...

  6. 【算法】《algorithm-note》算法笔记中文版正式发布!

    无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...

  7. c++ string 删除字符_算法笔记|(5)第二章C、C++的快速入门字符数组的存放方式string.h文件...

    字符数组的存放方式 由于字符数组是由若干个char类型的元素组成的,因此字符数组的每一位都是一个char字符,除此之外,在一维字符数组或者二维字符数组的第二维的末尾都有一个空字符\0表示存放的字符串的 ...

  8. 算法笔记(JavaScript版)——排序

    算法笔记(JavaScript版)--排序 本文内容根据Rebert Sedgewick和Kevin Wayne的<算法(第四版)>整理,原代码为java语言,自己修改为JavaScrip ...

  9. 三维重建7:Visual SLAM算法笔记

    VSLAM研究了几十年,新的东西不是很多,三维重建的VSLAM方法可以用一篇文章总结一下. 此文是一个好的视觉SLAM综述,对视觉SLAM总结比较全面,是SLAM那本书的很好的补充.介绍了基于滤波器的 ...

  10. 最优化理论与算法笔记

    最优化理论与算法笔记

最新文章

  1. 中职 学生学php学什么区别,职业高中和中专的区别是什么?哪个学历高
  2. 星巴克和阿里“结婚”,这后面真的不简单
  3. 数据库的binlog、redolog以及undolog
  4. Java数据类型和MySql数据类型对应表
  5. PTA —— 基础编程题目集 —— 编程题 —— 7-2 然后是几点 (15 分)
  6. 《MySQL 8.0.22执行器源码分析(3.2)关于HashJoinIterator》
  7. Vue3 高级语法(一)—— h函数、jsx
  8. web 前端 如何分享到instagram_如何找到靠谱的Web培训机构?web前端培训机构哪个好?...
  9. matplotlib画图_漂亮,超详细的matplotlib画图基础
  10. Java的三大特性:封装、继承、多态
  11. vscode如何添加头部注释、作者注释
  12. mysql my.cnf中忽略大小写_修改my.cnf ,使mysql 的表面不区分大小写
  13. python循环语句打印矩形_pycharm软件python的一些循环语句的用法
  14. 在Sql Server上安装插件Sql Prompt
  15. Windows系统重装教程完整版(系统备份、系统还原与重装)
  16. 软考-信息系统项目管理师-信息系统与信息化
  17. 2021CCPC东北四省赛 K. City 并查集
  18. 网上图书商城项目学习笔记-018生成订单
  19. 刷题笔记 | 朋友圈、岛屿的最大面积、岛屿数量
  20. 符号配对(C语言利用栈堆)

热门文章

  1. PIL 转opencv
  2. vmware linux系统 ip,修改虚拟机上Linux系统的IP地址
  3. Leetcode 51. N 皇后 (每日一题 20211008)
  4. Leetcode 46.全排列 (每日一题 20210621)
  5. 决策树ID3和C4.5算法Python实现源码
  6. 深入Python(5):递归
  7. java 程序片段_20个非常有用的Java程序片段
  8. 知识点讲解五:处理js异步加载问题
  9. Python编程基础:第四十一节 继承Inheritance
  10. NP-Hard问题及组合最优化问题