数据结构和算法11 之基础排序

简介:

前10节我们学习了一些经典的数据结构,从这节开始,我们将学习一些排序算法。这一节我们先学习几个基础排序算法:冒泡排序,选择排序和插入排序。

1. 冒泡排序

        冒泡排序算法运行起来非常慢,但在概念上它是排序算法中最简单的,因此冒泡排序算法在刚开始研究排序技术时是一个非常好的算法。冒泡排序算法的基本流程是:每一轮从头开始两两比较,将较大的项放在较小项的右边,这样每轮下来保证该轮最大的数在最右边。

算法程序如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void bubbleSort(int[] source) {  
  2.     for(int i = source.length - 1; i > 0; i--) {  
  3.         for(int j = 0; j < i; j++) {  
  4.             if(a[j] > a[j+1])  
  5.                 swap(source, j, j+1); //交换,具体实现略  
  6.         }  
  7.     }  
  8. }  

        冒泡排序算法还有个可以改进的地方,就是在算法中加入一个布尔变量标识该轮有没有进行数据的交换,若在某一次排序中未发现气泡位置的交换,则说明待排序的无序区中所有的项均已满足排序后的结果。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void bubbleSort(int[] source) {  
  2.     boolean exchange;  
  3.     for(int i = source.length - 1; i > 0; i--) {  
  4.         exchange = false;  
  5.         for(int j = 0; j < i; j++) {  
  6.             if(a[j] > a[j+1])  
  7.                 swap(source, j, j+1);  
  8.             exchange = true;  
  9.         }  
  10.         if(!exchange) return;  
  11.     }  
  12. }  

        算法分析:冒泡排序最好的情况是初始状态是正序的,一次扫描即可完成排序,所以最好的时间复杂度为O(N);最坏的情况是反序的,此时最坏的时间复杂度为O(N2)。平均情况,每轮N/2次循环,N轮时间复杂度为O(N2)。

        算法是稳定的,因为当a=b时,由于只有大于才做交换,故a和b的位置没有机会交换,所以算法稳定。

        空间复杂度为O(1),不需要额外空间。

2. 选择排序

选择排序改进了冒泡排序,将必要的交换次数从O(n2)减少到O(n),但是比较次数仍保持为O(n2)。冒泡排序每比较一次就可能交换一次,但是选择排序是将一轮比较完后,把最小的放到最前的位置(或者把最大的放到最后)。选择排序为大记录量的排序提出了一个非常重要的改进,因为这些大量的记录需要在内存中移动,这就使交换的时间和比较的时间相比起来,交换的时间更为重要。(一般在Java中不是这种情况,因为java中只是改变了引用位置,而实际对象的位置并没有发生改变。)

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void selectSort(int[] source) {    
  2.     int min;    
  3.     for(int i = 0; i < source.length; i++) {    
  4.         min = i;    
  5.         for(int j = i + 1; j < source.length; j++) {    
  6.             if(a[j] < a[min])    
  7.                 min = j;      
  8.         }    
  9.         swap(i, min);    
  10.     }    
  11. }    

        算法分析:选择排序最好和最坏的情况一样运行了O(N2)时间,但是选择排序无疑更快,因为它进行的交换少得多,当N值较小时,特别是如果交换时间比比较时间大得多时,选择排序实际上是相当快的。平均复杂度也是O(N2)。

        算法是不稳定的,假设a=b,且a在b前面,而某轮循环中最小值在b后面,而次最小值需要跟a交换,这时候b就在a前面了,所以选择排序是不稳定的。

        空间复杂度为O(1),不需要额外的空间。

3. 插入排序

        插入排序的实现步骤为:从第一个元素开始,该元素可以认为已经被排序 -> 取出下一个元素,在已经排序的元素序列中从后向前扫描 -> 如果该元素小于前一个元素,则将两者调换,再与前一个元素比较–> 重复第三步,直到找到已排序的元素小于或者等于新元素的位置 -> 将新元素插入到该位置中 -> 重复第二步

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void insertSort(int[] source) {  
  2.     for(int i = 1; i < source.length; i++) {  
  3.         for(int j = i; (j > 0) && (source[j] < source[j-1]); j--) {  
  4.             swap(j, j-1);  
  5.         }  
  6.     }  
  7. }  

        算法分析:插入排序最好的情况是序列已经是升序排列了,在这种情况下,需要进行N-1次比较即可,时间复杂度为O(N),最坏的情况是序列降序排列,这时候时间复杂度为O(N2)。因此插入排序不适合对于数据量比较大的排序应用。但是如果需要排序的数据量很小(如小于千),那么插入排序还是一个不错的选择。插入排序平均时间复杂度为O(N2),但是它要比冒泡排序快一倍,比选择排序还要快一点,经常被用在较复杂的排序算法的最后阶段,例如快速排序。

        算法是稳定的,假设a=b,且a在b的前面,其排序位置必然比b先确定,而后面再插入b时,必然在a的后面,所以是稳定的。

        空间复杂度为O(1),不需要额外的空间。

        以上三种排序是排序算法中比较基础的,也相对容易理解,就介绍到这里。如有错误,欢迎留言指正~+

转载:http://blog.csdn.net/eson_15/article/details/51154989

目录
相关文章
|
3天前
|
存储 算法 Java
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
32 9
 算法系列之数据结构-二叉树
|
2天前
|
算法 Java
算法系列之数据结构-二叉搜索树
二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,它能够高效地进行查找、插入和删除操作。二叉查找树的特点是,对于树中的每个节点,其左子树中的所有节点都小于该节点,而右子树中的所有节点都大于该节点。
43 22
|
1月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
88 29
|
1月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》图、查找、排序专题考点(含解析)
408考研——《数据结构》图,查找和排序专题考点选择题汇总(含解析)。
79 29
|
1月前
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
99 25
|
1月前
|
存储 人工智能 算法
C 408—《数据结构》算法题基础篇—数组(通俗易懂)
408考研——《数据结构》算法题基础篇之数组。(408算法题的入门)
72 23
|
2月前
|
存储 人工智能 算法
【C++数据结构——内排序】二路归并排序(头歌实践教学平台习题)【合集】
本关任务是实现二路归并算法,即将两个有序数组合并为一个有序数组。主要内容包括: - **任务描述**:实现二路归并算法。 - **相关知识**: - 二路归并算法的基本概念。 - 算法步骤:通过比较两个有序数组的元素,依次将较小的元素放入新数组中。 - 代码示例(以 C++ 为例)。 - 时间复杂度为 O(m+n),空间复杂度为 O(m+n)。 - **测试说明**:平台会对你编写的代码进行测试,提供输入和输出示例。 - **通关代码**:提供了完整的 C++ 实现代码。 - **测试结果**:展示代码运行后的排序结果。 开始你的任务吧,祝你成功!
42 10
|
2月前
|
搜索推荐 算法 数据处理
【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】
本文介绍了希尔排序算法的实现及相关知识。主要内容包括: - **任务描述**:实现希尔排序算法。 - **相关知识**: - 排序算法基础概念,如稳定性。 - 插入排序的基本思想和步骤。 - 间隔序列(增量序列)的概念及其在希尔排序中的应用。 - 算法的时间复杂度和空间复杂度分析。 - 代码实现技巧,如循环嵌套和索引计算。 - **测试说明**:提供了测试输入和输出示例,帮助验证代码正确性。 - **我的通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了代码运行的测试结果。 通过这些内容,读者可以全面了解希尔排序的原理和实现方法。
63 10
|
2月前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
54 7
|
2月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
55 2