数据结构与算法之二 排序

简介: 数据结构与算法之二 排序

 视频解析  https://edu.csdn.net/course/play/7813

假定,你要为你的生日聚会邀请你的朋友和亲戚。对此,你需要给他们打电 话。 你正在拥有 10,000 条记录的电话本中查找名为 Steve 的电话号码。 然而,电话本中的记录是以随意顺序存储的。 要在这样一个目录中查找你朋友的电话号码,你需要按顺序在目录中浏览每 个条目。 这将非常耗时, 你如何解决此问题呢?

 


节省时间和高效搜索数据的简单解决方案是排序。

排序 是按照某些预定义的顺序或序列排列数据的过程。 此顺序可以是升序 或降序。

如果数据被排序,则可以直接转到存储以 ‘ S ’ 开头的姓名部分,因此减少了要 遍历的记录数。

选择排序算法

通过使用一算法实现在程序中排序。

一些排序算法有:

冒泡(Bubble)排序

选择排序

插入排序

壳(Shell)排序

合并排序

快速排序

堆排序

要选择合适的算法,你需要考虑以下方面:

执行时间

存储空间

编程工作

冒泡排序算法:

是最简单的排序算法之一

此算法具有二次方程增长阶,因此适合仅排序小列表

通过列表重复扫描、比较相邻元素和按错误顺序交换,此算法会有作用 .

编写一算法以实现冒泡排序。


冒 泡排序的算法是:

1.设置通道(圈数) = 1。

2.重复步骤3  区分0到n – 1通道中的j。

1.如果索引j处的元素大于索引j + 1处的元素,则交换这两个元素。

3.按1递增通道;圈数加1

4.如果通道 <= n-1,则转到第2步。

排序算法的效率按照比较次数来测量。


在 冒 泡排序中,通道 1 内有 n – 1 次比较,通道 2 中有 n – 2 次比较,依此类推。

比较总数 = (n – 1) + (n – 2) + (n – 3) + … + 3 + 2 + 1 = n(n – 1)/2 。

n(n – 1)/2 是 O(n2) 阶的级数。 因此, 冒 泡排序算法是阶 O(n2) 的算法。

什么是冒泡排序算法的增长阶?


答案:

n – 1 次比较

答案:

冒泡排序算法具有二次方增长阶

当实现冒泡排序算法时,在通道1中将执行多少次比较?


答案:

n – 1 次比较

使用选择排序来排序数据

选择排序算法:

选择排序还具有二次方程增长阶,且因此仅适用于排序小的列表。

选择排序通过列表反复扫描,每次扫描选择一项,然后将这一项移动到列表中 正确的位置。

要理解选择排序算法的实现,考虑数组中存储的未排序的数字列表。每次都寻找最小值,将最小值往前放

编写一算法以实现选择排序。

选择排序的算法:

1. 重复步骤 2 和 3 区分 0 到 n -2 通道中的 j

2. 找出 arr[j] 到 arr[n – 1] 中的最小值 :

a. 设置 min_index = j

b. 重复步骤 c 区分 j + 1 到 n – 1 的 i

c. 如果 arr[i] < arr[min_index]:

 i.    min_index = i

3. 将 arr[j] 与 arr[min_index] 交换

在选择排序中, 在查找最小元素的通道 1 中有 n – 1 次比较。 在查找第二个最 小元素的通道 2 中有 n -2 次比较,依此类推。

比较总数 = (n – 1) + (n – 2) + (n – 3) + … + 3 + 2 + 1 = n(n – 1)/2

n(n – 1)/2 是 O(n2) 阶的级数。 因此,选择排序算法是阶 O(n2) 的算法。

插入排序算法:

具有二次方程增长阶,且因此仅用于排序小列表。

如果需要排序的列表几乎已经排序,则插入排序比冒泡排序和选择排序更有效 率。

要理解插入排序算法的实现,考虑数组中存储的未排序的数字列表。


要使用插入排序算法排序此列表:


你需要将列表分为两个子列表,即排序和未排序。

若要通过使用插入排序排序大小为n的列表,您需要执行(n– 1) 次通道。


最佳用例效率:

当列表已经被排序时产生最佳用例。

在这种情况下,您必须在每个通道中仅做一次比较。

在 n – 1 次通道中,您将需要做 n – 1 次比较。

插入排序的最佳用例效率是 O(n) 阶的。

最糟用例效率 :

当列表按反向顺序排序时产生最糟用例效率。

在这种情况下,您需要在第 1 个通道中做 1 次比较,在第二个通道中做 2 次比较, 在第 3 个通道中做 3 次比较,在第 n – 1 个通道中做 n – 1 次比较。

插入排序的最糟用例效率是 O(n2) 阶的。

销售经理对 2004-2006 念市场上最佳冷饮销售员进行调查。 David 是一名软 件开发人员,他有一个冷饮品牌及其销售数据的文件。 David 必须向销售经 理提供排序好的数据。 文件总的数据或多或少都要进行排序。 存储此数据 最有效率的排序算法是哪个?为什么?

记录是以随意顺序存储的。    


答案:

当列表部分排序时,插入排序提供了比泡泡排序和选择排序更好的有效。因此David应使用插入排序算法。

壳排序算法:

只要此列表已经部分排序且造成平均用例中的无效解决方案,则插入算法是高 效算法。

为了克服此限制,计算机科学家 D.L. Shell 提议改进插入排序算法。

新的算法称为壳( Shell )排序,是按照他的姓名命名的。

壳排序:


通过按若干位置的 距离 形成 多个子列表 分隔元素并进行比较来改进插入排序算 法

对 每个子列表 应用 插入排序 使元素朝着其正确的位置移动

帮助元素快速靠近正确的位置,因此减少了比较的次数

小结


在本章中,你已经学到:

排序是按照某些预定义的顺序或关键值排列数据的过程。 此顺序可以是升序或 降序。

用于排序数据有各种排序算法。 其中一些如下:

冒 泡排序

选择排序

插入排序

壳排序

合并排序

快速排序

堆排序

若要选择合适的算法,您需要考虑以下内容:

执行时间

存储空间

编程工作

冒泡排序和选择排序算法具有二次方程增长阶,且因此仅适用于排序小的列表。

插入排序执行不同次数的比较,这取决于最初的元素分阶。 当元素已经处于排 序阶,则插入排序需要进行极少比较。

如果需要排序的列表几乎已经排序,则插入排序比冒泡排序和选择排序更有效率。

通过比较按若干位置的距离分隔的元素,壳排序改善了插入排序 。 这帮助元素快 速靠近正确的位置,因此减少了比较的次数。

/**********************************************************/

/*描述:编写程序将10个学生的得分存储到数组中。通过使用冒泡排序算法,来排序数组中的元素,排序数组后,显示排序后数组的元素*/
using System;
class List
{
  //定义长度为20的整型数组
  private int[]a=new int[20]; //20是最大长度.
  //数组的个数
  private int n;
  //定义一个方法读取数据元素到数组
  public void read()
  {
      //获得
      while(true)
      {
        Console.WriteLine("请输入数组元素的个数<20之内>:");
        string s=Console.ReadLine();
        n=Int32.Parse(s);//转换为整型.Convert.ToInt32(s)
        if(n<=20)
          break;  //跳出循环
        else
          Console.WriteLine("\n数组只能够容纳20个数组元素.\n"); 
      }//while结束.
      Console.WriteLine("");
      Console.WriteLine("----------------------------------");
      Console.WriteLine("-----请输入数组元素---------------");
      Console.WriteLine("----------------------------------");
      //用户将数句元素输入数组
      for(int i=0;i<n;i++)
      {
        Console.Write("<"+(i+1)+">");
        string s1=Console.ReadLine();
        a[i]=Int32.Parse(s1); 
      }//<1>20 <2>20 <3>90
  }
  //*************************显示数组元素*************************
  public void display()
  {
    Console.WriteLine("");
    Console.WriteLine("-------------------------------------------");
    Console.WriteLine("------------排序过后的元素-----------------");
    Console.WriteLine("-------------------------------------------"); 
    for(int j=0;j<n;j++)
    {
      Console.WriteLine(a[j]);  
    }
  }
  /***************冒泡排序方法***************************/
  public void BubbleSortArray()
  {
    //圈数1--->n-1
    for(int i=1;i<=n-1;i++) //i:1;不是数组下标,是通道次数
    {
      //里面做的工作是两个相邻数字的比较;如果不符合升序排列,则交换.j指数组下标.
      for(int j=0;j<n-i;j++)  //注意:比较n-i次
      {
        if(a[j]>a[j+1]) //则说明不符合升序排列,需要交换
        {
          int temp;
          temp =a[j];
          a[j]=a[j+1];
          a[j+1]=temp;  
        }
      }//内层交换结束
    }//圈数循环结束.
  }
  /******************Main()方法*********************/
  public static void Main(string[]args)
  {
    List myList=new List();
    myList.read();  //读取数据元素
    myList.BubbleSortArray(); //调用冒泡排序算法
    myList.display();         //显示数组元素
    Console.WriteLine("\n\n按任意键退出.");
    Console.Read();
  }
}


--------------------------

/*
描述:使用选择排序,来排列包含10个学生得分的整数数组,升序排列.
*/
using System;
class Selection
{
  //定义数组的大小
  private int[]a=new int[20];   
  //数组元素的个数.
  private int n;
  //定义接受数组元素的函数 
  void read()
  {
    while(true)
    {
      Console.WriteLine("请输入数组元素的个数:");
      string s=Console.ReadLine();
      n=Int32.Parse(s);
      if(n<=20)
        break;
      else
        Console.WriteLine("\n数组只能够接收20个元素.\n");
    }
    Console.WriteLine("");
    Console.WriteLine("---------------------------------");
    Console.WriteLine("----------请输入数组元素---------");
    Console.WriteLine("---------------------------------");
    //用户输入数据
    for(int i=0;i<n;i++)
    {
      Console.Write("<"+(i+1)+">");
      string  s1=Console.ReadLine();
      a[i]=Int32.Parse(s1);
    } 
  }
  //显示数组内容的函数
  void display()
  {
    Console.WriteLine("");
    Console.WriteLine("---------------------------------");
    Console.WriteLine("----------排序后的数组元素-------");
    Console.WriteLine("---------------------------------");
    for(int j=0;j<n;j++)
    {
      Console.WriteLine(a[j]);
    }
  }
/*
  选择排序算法:每次选择最小值,将其依次往前排;借助于下标标记来实现.
*/
  public void SelectionSortArray()
  {
    //外面进行了n-1圈
    for(int i=0;i<n-1;i++)
    {
      //定义个指示最小值标记的变量
      int min_index=i;
      //查找选择最小值所对应的标记(下标)
      for(int j=i+1;j<=n-1;j++)
      {
        //判断如果有值比,最小值下标对应的数还小,则将该值对应的下标给min_index
        if(a[j]<a[min_index])
          min_index=j;
      }//结束寻找最小值下标
      //交换:a[i]<-->a[min_index]
      swap(i,min_index);  //调用交换方法.
    } 
  }
  //交换两个值的方法
  public void swap(int x,int y)
  {
    int temp;
    temp=a[x];
    a[x]=a[y];
    a[y]=temp;
  }
  //类的主方法
  public static void Main()
  {
    Selection sec=new Selection();
    sec.read();
    sec.SelectionSortArray();
    sec.display();
    Console.WriteLine("\n\n请按任意键结束!.");
    Console.Read(); 
  }
}

---------------------

/*
描述:使用插入排序,来排列包含10个学生得分的整数数组。
*/
using System;
class Insertion
{
  //定义数组的大小
  private int[]a=new int[20];   
  //数组元素的个数.
  private int n;
  //定义接受数组元素的函数 
  void read()
  {
    while(true)
    {
      Console.WriteLine("请输入数组元素的个数:");
      string s=Console.ReadLine();
      n=Int32.Parse(s);
      if(n<=20)
        break;
      else
        Console.WriteLine("\n数组只能够接收20个元素.\n");
    }
    Console.WriteLine("");
    Console.WriteLine("---------------------------------");
    Console.WriteLine("----------请输入数组元素---------");
    Console.WriteLine("---------------------------------");
    //用户输入数据
    for(int i=0;i<n;i++)
    {
      Console.Write("<"+(i+1)+">");
      string  s1=Console.ReadLine();
      a[i]=Int32.Parse(s1);
    } 
  }
  //显示数组内容的函数
  void display()
  {
    Console.WriteLine("");
    Console.WriteLine("---------------------------------");
    Console.WriteLine("----------排序后的数组元素-------");
    Console.WriteLine("---------------------------------");
    for(int j=0;j<n;j++)
    {
      Console.WriteLine(a[j]);
    }
  }
  //****使用插入排序的方法
public void InsertionSortArray()
{
    //重复n-1次来将为排序列表数据放入已排序列表
    for(int i=1;i<n;i++)
    {
    int temp=a[i];
    int j=i-1;
    //如果j>=0或大于临时值,则执行如下操作
    while((j>=0)&&(a[j]>temp))
    {
      a[j+1]=a[j];
      j--;  
    }
    a[j+1]=temp;
  }
}
  //交换两个值的方法
  public void swap(int x,int y)
  {
    int temp;
    temp=a[x];
    a[x]=a[y];
    a[y]=temp;
  }
  //类的主方法
  public static void Main()
  {
    Insertion sec=new Insertion();
    sec.read();
    sec.InsertionSortArray();
    sec.display();
    Console.WriteLine("\n\n请按任意键结束!.");
    Console.Read(); 
  }
}


--------------------------------------------------------

/*
描述:使用插入排序,来排列包含10个学生得分的整数数组。
*/
using System;
class ShellSorter
{ 
  //数组元素的个数.
  private static int n=0;
  //定义数组的大小
  private int[]a;   
  //定义接受数组元素的函数 
  void read()
  {
    while(true)
    {
      Console.WriteLine("请输入数组元素的个数:");
      string s=Console.ReadLine();
      n=Int32.Parse(s);
      a=new int[n];
      if(n<=20)
        break;
      else
        Console.WriteLine("\n数组只能够接收20个元素.\n");
    }
    Console.WriteLine("");
    Console.WriteLine("---------------------------------");
    Console.WriteLine("----------请输入数组元素---------");
    Console.WriteLine("---------------------------------");
    //用户输入数据
    for(int i=0;i<n;i++)
    {
      Console.Write("<"+(i+1)+">");
      string  s1=Console.ReadLine();
      a[i]=Int32.Parse(s1);
    } 
  }
  //显示数组内容的函数
  void display()
  {
    Console.WriteLine("");
    Console.WriteLine("---------------------------------");
    Console.WriteLine("----------排序后的数组元素-------");
    Console.WriteLine("---------------------------------");
    for(int j=0;j<n;j++)
    {
      Console.Write("  "+a[j]);
    }
  }
  //****使用希尔排序的方法
        public void ShellSort()
        {           
            for (int step = a.Length/ 2; step >= 1; step = step / 2)
            {
                for (int i = step; i < a.Length; i+=step)                
                {
                    int temp = a[i];
                    int j = i - step;
                    while (j >= 0 && temp < a[j])
                    {
                        a[j + step] = a[j];
                        j-=step;
                    }
                    a[j + step] = temp;
                }
            }
        }
  //交换两个值的方法
  public void swap(int x,int y)
  {
    int temp;
    temp=a[x];
    a[x]=a[y];
    a[y]=temp;
  }
  //类的主方法
  public static void Main()
  {
    ShellSorter sec=new ShellSorter();
    sec.read();
    sec.ShellSort();
    sec.display();
    Console.WriteLine("\n\n请按任意键结束!.");
    Console.Read(); 
  }
}
目录
相关文章
|
1天前
|
存储 人工智能 算法
【C++数据结构——内排序】二路归并排序(头歌实践教学平台习题)【合集】
本关任务是实现二路归并算法,即将两个有序数组合并为一个有序数组。主要内容包括: - **任务描述**:实现二路归并算法。 - **相关知识**: - 二路归并算法的基本概念。 - 算法步骤:通过比较两个有序数组的元素,依次将较小的元素放入新数组中。 - 代码示例(以 C++ 为例)。 - 时间复杂度为 O(m+n),空间复杂度为 O(m+n)。 - **测试说明**:平台会对你编写的代码进行测试,提供输入和输出示例。 - **通关代码**:提供了完整的 C++ 实现代码。 - **测试结果**:展示代码运行后的排序结果。 开始你的任务吧,祝你成功!
22 10
|
1天前
|
搜索推荐 算法 数据处理
【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】
本文介绍了希尔排序算法的实现及相关知识。主要内容包括: - **任务描述**:实现希尔排序算法。 - **相关知识**: - 排序算法基础概念,如稳定性。 - 插入排序的基本思想和步骤。 - 间隔序列(增量序列)的概念及其在希尔排序中的应用。 - 算法的时间复杂度和空间复杂度分析。 - 代码实现技巧,如循环嵌套和索引计算。 - **测试说明**:提供了测试输入和输出示例,帮助验证代码正确性。 - **我的通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了代码运行的测试结果。 通过这些内容,读者可以全面了解希尔排序的原理和实现方法。
24 10
|
1天前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
21 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
158 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
132 8
|
3月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
104 9
|
3月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
48 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
3月前
|
存储 搜索推荐 算法
【用Java学习数据结构系列】七大排序要悄咪咪的学(直接插入,希尔,归并,选择,堆排,冒泡,快排)以及计数排序(非比较排序)
【用Java学习数据结构系列】七大排序要悄咪咪的学(直接插入,希尔,归并,选择,堆排,冒泡,快排)以及计数排序(非比较排序)
36 1
|
3月前
|
搜索推荐 索引
【初阶数据结构】深度解析七大常见排序|掌握底层逻辑与原理(二)
【初阶数据结构】深度解析七大常见排序|掌握底层逻辑与原理
|
3月前
|
搜索推荐 C++
【初阶数据结构】深度解析七大常见排序|掌握底层逻辑与原理(一)
【初阶数据结构】深度解析七大常见排序|掌握底层逻辑与原理