在一些公司面试中,数据结构与算法一般都是大公司都会考的题目,而小公司考得很少。考试题目一般集中排序算法与时间复杂度、链表结构的应用。
一、排序算法与复杂度
常用排序算法的时间复杂度和空间复杂度
排序法
|
最差时间分析
|
平均时间复杂度
|
稳定度
|
空间复杂度
|
冒泡排序
|
O(n2)
|
O(n2)
|
稳定
|
O(1)
|
快速排序
|
O(n2)
|
O(n*log2n)
|
不稳定
|
O(log2n)~O(n)
|
选择排序
|
O(n2)
|
O(n2)
|
稳定
|
O(1)
|
二叉树排序
|
O(n2)
|
O(n*log2n)
|
不一顶
|
O(n)
|
插入排序
|
O(n2)
|
O(n2)
|
稳定
|
O(1)
|
堆排序
|
O(n*log2n)
|
O(n*log2n)
|
不稳定
|
O(1)
|
希尔排序
|
O
|
O
|
不稳定
|
O(1)
|
1、时间复杂度
(1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。
(2)时间复杂度 在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度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),..., k次方阶O(nk),指数阶O(2n)。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。 2、空间复杂度 与时间复杂度类似,空间复杂度是指算法在计算机内执行时所需存储空间的度量。记作: S(n)=O(f(n)) 我们一般所讨论的是除正常占用内存开销外的辅助存储单元规模。讨论方法与时间复杂度类似,不再赘述。
(3)渐进时间复杂度评价算法时间性能 主要用算法时间复杂度的数量级(即算法的渐近时间复杂度)评价一个算法的时间性能。
2、类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。
空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。存储算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。算法在运行过程中临时占用的存储空间随算法的不同而异,有的算法只需要占用少量的临时工作单元,而且不随问题规模的大小而改变,我们称这种算法是“就地\"进行的,是节省存储的算法,如这一节介绍过的几个算法都是如此;有的算法需要占用的临时工作单元数与解决问题的规模n有关,它随着n的增大而增大,当n较大时,将占用较多的存储单元,例如将在第九章介绍的快速排序和归并排序算法就属于这种情况。
如当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1);当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为0(10g2n);当一个算法的空I司复杂度与n成线性比例关系时,可表示为0(n).若形参为数组,则只需要为它分配一个存储由实参传送来的一个地址指针的空间,即一个机器字长空间;若形参为引用方式,则也只需要为其分配存储一个地址的空间,用它来存储对应实参变量的地址,以便由系统自动引用实参变量。
各种算法汇总:
/*
================================================
功能:选择排序
输入:数组名称(也就是数组首地址)、数组中元素个数
================================================
*/
/*
====================================================
算法思想简单描述:
在要排序的一组数中,选出最小的一个数与第一个位置的数交换;
然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环
到倒数第二个数和最后一个数比较为止。
选择排序是不稳定的。算法复杂度O(n2)--[n的平方]
=====================================================
*/
void select_sort(int *x, int n)
{
int i, j, min, t;
for (i=0; i<n-1; i++) /*要选择的次数:0~n-2共n-1次*/
{
min = i; /*假设当前下标为i的数最小,比较后再调整*/
for (j=i+1; j<n; j++)/*循环找出最小的数的下标是哪个*/
{
if (*(x+j) < *(x+min))
{
min = j; /*如果后面的数比前面的小,则记下它的下标*/
}
}
if (min != i) /*如果min在循环中改变了,就需要交换数据*/
{
t = *(x+i);
*(x+i) = *(x+min);
*(x+min) = t;
}
}
}
/*
================================================
功能:直接插入排序
输入:数组名称(也就是数组首地址)、数组中元素个数
================================================
*/
/*
====================================================
算法思想简单描述:
在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排
好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数
也是排好顺序的。如此反复循环,直到全部排好顺序。
直接插入排序是稳定的。算法时间复杂度O(n2)--[n的平方]
=====================================================
*/
void insert_sort(int *x, int n)
{
int i, j, t;
for (i=1; i<n; i++) /*要选择的次数:1~n-1共n-1次*/
{
/*
暂存下标为i的数。注意:下标从1开始,原因就是开始时
第一个数即下标为0的数,前面没有任何数,单单一个,认为
它是排好顺序的。
*/
t=*(x+i);
for (j=i-1; j>=0 && t<*(x+j); j--) /*注意:j=i-1,j--,这里就是下标为i的数,在它前面有序列中找插入位置。*/
{
*(x+j+1) = *(x+j); /*如果满足条件就往后挪。最坏的情况就是t比下标为0的数都小,它要放在最前面,j==-1,退出循环*/
}
*(x+j+1) = t; /*找到下标为i的数的放置位置*/
}
}
/*
================================================
功能:冒泡排序
输入:数组名称(也就是数组首地址)、数组中元素个数
================================================
*/
/*
====================================================
算法思想简单描述:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上
而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较
小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要
求相反时,就将它们互换。
下面是一种改进的冒泡算法,它记录了每一遍扫描后最后下沉数的
位置k,这样可以减少外层循环扫描的次数。
冒泡排序是稳定的。算法时间复杂度O(n2)--[n的平方]
=====================================================
*/
void bubble_sort(int *x, int n)
{
int j, k, h, t;
for (h=n-1; h>0; h=k) /*循环到没有比较范围*/
{
for (j=0, k=0; j<h; j++) /*每次预置k=0,循环扫描后更新k*/
{
if (*(x+j) > *(x+j+1)) /*大的放在后面,小的放到前面*/
{
t = *(x+j);
*(x+j) = *(x+j+1);
*(x+j+1) = t; /*完成交换*/
k = j; /*保存最后下沉的位置。这样k后面的都是排序排好了的。*/
}
}
}
}
/*
================================================
功能:希尔排序
输入:数组名称(也就是数组首地址)、数组中元素个数
================================================
*/
/*
====================================================
算法思想简单描述:
在直接插入排序算法中,每次插入一个数,使有序序列只增加1个节点,
并且对插入下一个数没有提供任何帮助。如果比较相隔较远距离(称为
增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除
多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现
了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中
记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量
对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成
一组,排序完成。
下面的函数是一个希尔排序算法的一个实现,初次取序列的一半为增量,
以后每次减半,直到增量为1。
希尔排序是不稳定的。
=====================================================
*/
void shell_sort(int *x, int n)
{
int h, j, k, t;
for (h=n/2; h>0; h=h/2) /*控制增量*/
{
for (j=h; j<n; j++) /*这个实际上就是上面的直接插入排序*/
{
t = *(x+j);
for (k=j-h; (k>=0 && t<*(x+k)); k-=h)
{
*(x+k+h) = *(x+k);
}
*(x+k+h) = t;
}
}
}
/*
================================================
功能:快速排序
输入:数组名称(也就是数组首地址)、数组中起止元素的下标
================================================
*/
/*
====================================================
算法思想简单描述:
快速排序是对冒泡排序的一种本质改进。它的基本思想是通过一趟
扫描后,使得排序序列的长度能大幅度地减少。在冒泡排序中,一次
扫描只能确保最大数值的数移到正确位置,而待排序序列的长度可能只
减少1。快速排序通过一趟扫描,就能确保某个数(以它为基准点吧)
的左边各数都比它小,右边各数都比它大。然后又用同样的方法处理
它左右两边的数,直到基准点的左右只有一个元素为止。它是由
C.A.R.Hoare于1962年提出的。
显然快速排序可以用递归实现,当然也可以用栈化解递归实现。下面的
函数是用递归实现的,有兴趣的朋友可以改成非递归的。
快速排序是不稳定的。最理想情况算法时间复杂度O(nlog2n),最坏O(n2)
=====================================================
*/
void quick_sort(int *x, int low, int high)
{
int i, j, t;
if (low < high) /*要排序的元素起止下标,保证小的放在左边,大的放在右边。这里以下标为low的元素为基准点*/
{
i = low;
j = high;
t = *(x+low); /*暂存基准点的数*/
while (i<j) /*循环扫描*/
{
while (i<j && *(x+j)>t) /*在右边的只要比基准点大仍放在右边*/
{
j--; /*前移一个位置*/
}
if (i<j)
{
*(x+i) = *(x+j); /*上面的循环退出:即出现比基准点小的数,替换基准点的数*/
i++; /*后移一个位置,并以此为基准点*/
}
while (i<j && *(x+i)<=t) /*在左边的只要小于等于基准点仍放在左边*/
{
i++; /*后移一个位置*/
}
if (i<j)
{
*(x+j) = *(x+i); /*上面的循环退出:即出现比基准点大的数,放到右边*/
j--; /*前移一个位置*/
}
}
*(x+i) = t; /*一遍扫描完后,放到适当位置*/
quick_sort(x,low,i-1); /*对基准点左边的数再执行快速排序*/
quick_sort(x,i+1,high); /*对基准点右边的数再执行快速排序*/
}
}
/*
================================================
功能:堆排序
margin: 0cm 0cm 0pt;
分享到:
相关推荐
前端面试资料2024年,大厂进阶秘诀,面试通过秘诀,这个年纪你怎么敢偷懒的??快背起来! 1.JavaScript面试真题-210页 2.CSS面试真题-127页 3.ES6面试真题-84页 4.Vue面试真题-237页 5.Vue3面试真题-44页 6.React...
2023java最新面试资料汇总,包含: 10万字总结java面试题和答案一份 阿里大佬总结的Java面试资料一份 面试汇总网盘资源一份 MIC老师最新面试文档一份 面试题包括以下十九部分:Java 基础、容器、多线程、反射、对象...
应届大学毕业生面试应答 涉世之初面试以实在取胜 毕业生面试四忌 着装与举止: 初次求职面试的适宜装扮 精心选择面试着装 求职面试中修饰与衣着 面试服装大忌 如何看待求职时的穿着 面试中的举止如何才算得当 ...
本压缩包“软件测试面试资料”提供了丰富的资源,涵盖了多个公司的面试需求,旨在帮助求职者充分准备,提高成功通过测试岗位面试的可能性。 1. **软件测试基础**:在面试中,面试官通常会询问测试的基本概念,如...
【MBA英语面试资料:为你的成功之路铺垫】 在当今全球化的商业环境中,MBA(工商管理硕士)教育已经成为许多专业人士提升职业竞争力的关键。而英语作为国际商务的主要语言,其在MBA面试中的重要性不言而喻。这份...
【PWC面试资料网上收集版】 PWC,全称普华永道,是全球四大会计师事务所之一,其面试流程严谨且竞争激烈。对于想要进入PWC工作的求职者来说,充分准备是至关重要的。这份“PWC面试资料网上收集版”集合了关键的面试...
这份"Java面试资料大全"包含了丰富的资源,旨在帮助Java程序员准备全面的面试,提高通过率。 首先,我们可以从阿里面试Java1到Java5的文档中,期待找到关于Java核心技术的深度解析。这些文档可能涵盖了以下几个方面...
4、Java最新2022版面试题及解答-阿里内部资料(266页) 内涵: 1、BATJ面试题汇总及详解(进大厂必看)(65页) 2、JAVA面试核心知识点整理(283页) 3、Java面试题2022最新版大合集(485页) 4、Java最新2022版面试题及解答-...
【前端面试资料.zip】是一个包含了全面的前端面试准备材料的压缩包。这个压缩包的核心是帮助应聘者在前端开发职位的面试中取得成功。通过深入学习和理解其中的内容,求职者可以提升自己的技术实力和面试技巧,从而在...
"最新的大厂面试资料全面"这一标题揭示了这是一份包含最新、最全的大型互联网公司(通常被称为“大厂”)Java面试题的资源集合。这样的资料对于求职者来说极具价值,因为它可以帮助他们了解并掌握各大公司对Java...
本资源"Java面试宝典2018-最全面试资料"是为Java开发者准备的一份全面的面试指南,旨在帮助求职者深入理解Java的核心概念和技术,以及如何在实际项目中应用它们。 1. **JavaSE**: Java Standard Edition是Java的...
这份名为"各大银行面试资料"的压缩包文件,显然是为了帮助求职者们更好地应对银行面试而精心编纂的。其中包含的2013年中国各大银行面试必备资料,将为我们揭示了银行招聘过程中可能遇到的问题类型、面试技巧以及如何...
### Java面试资料精讲分析 #### 一、程序员面试技巧概览 在IT行业中,面试是程序员进入一家公司的必经之路。为了帮助求职者更好地准备面试,本章节将重点介绍以下几点: - **简历制作**:如何撰写一份吸引人的...
【JAVA面试】相关的知识点涵盖了Java语言...以上内容是基于"张孝祥等八份JAVA面试资料总汇"中的主要知识点,涵盖了Java程序员面试的大部分领域。通过深入学习和实践,能够为面试者提供坚实的技术基础和应对面试的自信。
这份“Java面试资料.zip”显然是一份专为准备Java开发者面试而设计的学习资源,旨在帮助求职者掌握Java核心技术,提高面试竞争力,从而有望获得年薪20万的职位。 在Java面试中,通常会涵盖以下几个关键知识点: 1....
这份“java面试资料大全”显然旨在帮助求职者充分准备,提高面试成功的概率。以下是对这份资料可能包含的关键知识点的详细解析: 1. **Java基础** - 类与对象:理解面向对象编程的基本概念,如封装、继承和多态。 ...
在Java领域,面试是每一位求职者必经的挑战。这份"2021大厂Java面试详细汇总"文档,无疑是准备面试的宝贵资源。...这份"2021大厂Java面试详细汇总"文档无疑是一份全面而实用的参考资料,值得每一位Java开发者仔细研读。
在前端开发领域,面试通常会涵盖多个关键知识点,这些知识点在"完整前端面试资料.zip"中有所体现。以下是根据压缩包文件名解析出的主要面试主题及相应的详细内容: 1. **TypeScript面试真题** (10.Typescript面试...
这份"JAVA面试资料"涵盖了核心的Java知识、MyBatis框架以及Spring框架的相关面试问题,为准备Java程序员面试的求职者提供了全面的参考资料。下面我们将深入探讨这些知识点。 首先,Java基础知识是面试的基石。这...
这份"java开发工程师面试资料.zip"文件显然是一份集中的学习资源,旨在帮助准备面试的开发者提升自己的竞争力。下面,我们将深入探讨其中可能包含的重要知识点,并提供一些与Java开发工程师面试相关的详细信息。 1....