2-1初级排序算法

2-1初级排序算法

概述

  • 排序=比较+交换

  • 排序算法的模板

    #include <iostream>
    #include <vector>
    using namespace std;
    //不同的排序算法
    class Soulution
    {
    public:
    	void sort(vector<int>& arr)
    	{
    
    	}
    	//比较两个元素返回较小值
    	bool less(int num1, int num2)
    	{
    		return num1 < num2;
    	}
    
    	//交换下标为i和j的两个元素
    	void exch(vector<int>& arr, int i, int j)
    	{
    		int temp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = temp;
    	}
    	//打印数组
    	void show(vector<int> arr)
    	{
    		for (int i = 0; i < arr.size(); i++)
    		{
    			cout << arr[i] << " ";
    		}
    	}
    	//判断数组是否递增
    	bool isSort(vector<int> arr)
    	{
    		int n = arr.size();
    		for (int i = 0; i < n-1; i++)
    		{
    			if(less(arr[i + 1], arr[i]))
    				return false;
    		}
    		return true;
    	}
    };
    //编写主函数
    int main()
    {
    	Soulution *so = new Soulution();
    	//测试数组
    	vector<int> arr = { 1,4,9,2,3,7,8,0,5 };
    	//排序
    	so->sort(arr);
    	//测试是否有序
    	cout<<so->isSort(arr)<<endl;
    	//输出排序之后的数组
    	so->show(arr);
    }
    

选择排序

  1. 算法思想–不断选择剩余元素中的较小者

    • 在数组中找到最小的那个元素,将最小的元素和第一个元素交换位置
    • 在剩下的元素中最小的元素,和第二个元素交换位置
    • 以此类推,直到整个数组排序
  2. 算法分析–时间复杂度为N^2

    • 每次交换确定一个元素,交换的次数是N,算法的效率取决于找到交换元素的比较次数
    • 第一趟比较N-1次,第二趟比较N-2次,第i趟比较N-i次
    • 所以N次交换需要比较N(N-1)/2次~1/2*(N^2)
    • 时间复杂度为N^2
  3. 特点

    • 运行时间和输入无关
    • 数据移动是最少的
  4. 模拟实例 { 1,4,9,2,3,7,8,0,5 }

    趟数/下标012345678
    原始数组149237805
    101
    2014
    30129
    401239
    5012349
    60123457
    701234578
    8012345789

    tips:空格表示和上一行保持一致

  5. 代码实现

    #include <iostream>
    #include <vector>
    using namespace std;
    //不同的排序算法
    class Soulution
    {
    public:
    	void sort(vector<int>& arr)
    	{
    		for (int i = 0; i < arr.size() - 1; i++)
    		{
    			int minIndex = i;
    			for (int j = i + 1; j < arr.size(); j++)
    			{
    				if (less(arr[j], arr[minIndex]))//找到第i轮最小的数
    					minIndex = j;				
    			}
    			exch(arr, minIndex, i);//第i轮最小的数和第i个数交换
    		}
    	}
    	//比较两个元素返回较小值
    	bool less(int num1, int num2)
    	{
    		return num1 < num2;
    	}
    
    	//交换下标为i和j的两个元素
    	void exch(vector<int>& arr, int i, int j)
    	{
    		int temp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = temp;
    	}
    	//打印数组
    	void show(vector<int> arr)
    	{
    		for (int i = 0; i < arr.size(); i++)
    		{
    			cout << arr[i] << " ";
    		}
    	}
    	//判断数组是否递增
    	bool isSort(vector<int> arr)
    	{
    		int n = arr.size();
    		for (int i = 0; i < n-1; i++)
    		{
    			if(less(arr[i + 1], arr[i]))
    				return false;
    		}
    		return true;
    	}
    };
    //编写主函数
    int main()
    {
    	Soulution *so = new Soulution();
    	//测试数组
    	vector<int> arr = { 1,4,9,2,3,7,8,0,5 };
    	//排序
    	so->sort(arr);
    	//测试是否有序
    	cout<<so->isSort(arr)<<endl;
    	//输出排序之后的数组
    	so->show(arr);
    }
    

插入排序

  1. 算法思想—不断把新的元素插入到正确的位置

    • 类似于扑克
    • 先随机选择一张牌作为第一张牌
    • 拿到第二张牌,比第一张牌大就插入到左边,否则插入到右边
    • 拿到第三张牌,再找到已经拍好序的前两中排中该插入的位置,然后插入
    • 拿到第i张牌,找到已经排好序中的前i-1张牌,插入到对应的位置
  2. 算法分析–时间复杂度为O(N^2)

    • 最坏的情况下

      选定一个元素,总共要插入n-1个元素

      找第二个元素插入的位置比较1次,需要有n-1个元素后移,交换n-1次

      找第三个元素插入的位置比较2次,需要有n-2个元素后移,交换n-2次

      找第n个元素插入的位置比较n-1次,需要有1个元素后移,交换1次

      所以比较的次数是(N-1)*(N-1)/2~N*N/2

      交换的次数是 (N-1)*(N-1)/2~N*N/2

    • 最好的情况下,已经排好序了,交换0次,比较N-1次

    • 平均需要~N^2/4次交换以及~N^2/4次比较

    • 插入排序在下列情况运用特别有效

      • 数组中每个元素距离它最终的位置都不远
      • 一个有序的大数组接一个小数组
      • 数组中只有几个元素的位置不正确
  3. 模拟排序

    趟数/初始值SORTEXAMPLE
    1OS
    2ORS
    3ORST
    4EROST
    5EROSTX
    6AEOSTOX
    7AEMORSTX
    8AEMOPRSTX
    9AELMOPRSTX
    10AEELMOPRSTX
  4. 代码

    • 交换实现插入排序
    #include <iostream>
    #include <vector>
    using namespace std;
    //不同的排序算法
    class Soulution
    {
    public:
    	void sort(vector<char>& arr)
    	{
    		int n = arr.size();
    		for (int i = 1; i < n ; i++)//从1号位置上的数开始,一直到最后一个数
    		{
    			for (int j = 0; j < i; j++)//寻找插入的位置,下标应该为0到i-1
    			{
    				if (less(arr[i], arr[j]))				//比较要插入的数和排序好的数,如果要插入的数比排序好的数大就换位置
    					exch(arr, i, j);
    			}
    		}
    	}
    	//比较两个元素返回较小值
    	bool less(char num1, char num2)
    	{
    		return num1 < num2;
    	}
    
    	//交换下标为i和j的两个元素
    	void exch(vector<char>& arr, int i, int j)
    	{
    		int temp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = temp;
    	}
    	//打印数组
    	void show(vector<char> arr)
    	{
    		for (int i = 0; i < arr.size(); i++)
    		{
    			cout << arr[i] << " ";
    		}
    	}
    	//判断数组是否递增
    	bool isSort(vector<char> arr)
    	{
    		int n = arr.size();
    		for (int i = 0; i < n-1; i++)
    		{
    			if(less(arr[i + 1], arr[i]))
    				return false;
    		}
    		return true;
    	}
    };
    //编写主函数
    int main()
    {
    	Soulution *so = new Soulution();
    	//测试数组
    	vector<char> arr = {'S','O','R','T','E','X','A','M','P','L','E'};
    	//排序
    	so->sort(arr);
    	//测试是否有序
    	cout<<so->isSort(arr)<<endl;
    	//输出排序之后的数组
    	so->show(arr);
    }
    
    • 向后移动实现插入排序

      #include <iostream>
      #include <vector>
      using namespace std;
      //不同的排序算法
      class Soulution
      {
      public:
      	void sort(vector<char>& arr)
      	{
      		int n = arr.size();
      		for (int i = 1; i < n ; i++)//从1号位置上的数开始,一直到最后一个数
      		{
      			for (int j = 0; j < i; j++)//寻找插入的位置,下标应该为0到i-1
      			{
      				if (less(arr[i], arr[j]))//比较要插入的数和排序好的数,如果要插入的数比排序好的数大,从这个数开始到插入的数原来的位置向后移动
      				{
      					int temp = arr[i];	//保存插入的数
      					
      					for (int k = i; k >j; k--)
      					{
      						arr[k] = arr[k - 1];
      					}
      					arr[j] = temp;//把元素插入到正确位置上
      					break;
      				}
      					
      			}
      		}
      	}
      	//比较两个元素返回较小值
      	bool less(char num1, char num2)
      	{
      		return num1 < num2;
      	}
      
      	//交换下标为i和j的两个元素
      	void exch(vector<char>& arr, int i, int j)
      	{
      		int temp = arr[i];
      		arr[i] = arr[j];
      		arr[j] = temp;
      	}
      	//打印数组
      	void show(vector<char> arr)
      	{
      		for (int i = 0; i < arr.size(); i++)
      		{
      			cout << arr[i] << " ";
      		}
      	}
      	//判断数组是否递增
      	bool isSort(vector<char> arr)
      	{
      		int n = arr.size();
      		for (int i = 0; i < n-1; i++)
      		{
      			if(less(arr[i + 1], arr[i]))
      				return false;
      		}
      		return true;
      	}
      };
      //编写主函数
      int main()
      {
      	Soulution *so = new Soulution();
      	//测试数组
      	vector<char> arr = {'S','O','R','T','E','X','A','M','P','L','E'};
      	//排序
      	so->sort(arr);
      	//测试是否有序
      	cout<<so->isSort(arr)<<endl;
      	//输出排序之后的数组
      	so->show(arr);
      }
      

希尔排序

  1. 算法思想

    使得数组中任意间隔为h的元素都是有序的

  2. 算法分析

    目前来说理解希尔排序的性能还是一项挑战

  3. 模拟排序

    选择不同的间隔,排序的方式会不一样,可参考哔哩哔哩视频

  4. 代码实现

    以插入间隔每次减少一半为例,inc表示这一轮的间距

    #include <iostream>
    #include <vector>
    using namespace std;
    //不同的排序算法
    class Soulution
    {
    public:
    	void sort(vector<char>& arr)
    	{
    		int n = arr.size(),j=0;
    		//设置哈希排序的增量
    		for (int inc = n / 2; inc > 0; inc = inc / 2)
    		{
    			//插入排序,顺序为第一个数到最后一个数,依次在所在的组进行希尔排序
    			for (int i = inc; i < n; i++)
    			{
    				int temp = arr[i];
    				for (j = i; j >= inc&& less(temp, arr[j-inc]); j=j-inc)
    				{					
    						arr[j] = arr[j - inc];					
    				}
    				arr[j] = temp;
    			}
    		}
    
    	}
    	//比较两个元素返回较小值
    	bool less(char num1, char num2)
    	{
    		return num1 < num2;
    	}
    
    	//交换下标为i和j的两个元素
    	void exch(vector<char>& arr, int i, int j)
    	{
    		int temp = arr[i];
    		arr[i] = arr[j];
    		arr[j] = temp;
    	}
    	//打印数组
    	void show(vector<char> arr)
    	{
    		for (int i = 0; i < arr.size(); i++)
    		{
    			cout << arr[i] << " ";
    		}
    	}
    	//判断数组是否递增
    	bool isSort(vector<char> arr)
    	{
    		int n = arr.size();
    		for (int i = 0; i < n-1; i++)
    		{
    			if(less(arr[i + 1], arr[i]))
    				return false;
    		}
    		return true;
    	}
    };
    //编写主函数
    int main()
    {
    	Soulution *so = new Soulution();
    	//测试数组
    	vector<char> arr = {'S','O','R','T','E','X','A','M','P','L','E'};
    	//排序
    	so->sort(arr);
    	//测试是否有序
    	cout<<so->isSort(arr)<<endl;
    	//输出排序之后的数组
    	so->show(arr);
    }
    
    
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值