一、 堆排序
堆:
大顶堆:每个结点的值都大于或等于其左右孩子结点的值,即arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 。
小顶堆:每个结点的值都小于或等于其左右孩子结点的值,即arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] 。
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。
实现过程:
①将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。
②将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。
③如此反复执行,便能得到一个有序序列了。
C++代码实现:
#include <iostream>
#include <vector>
using namespace std;
// 调节节点
void heapify(vector<int>& arr,int n,int i)
{
if(i>n)return;
int left=2*i+1;
int right=2*i+2;
int max=i,max_value;
if(arr[left]>=arr[max]&&left<=n)max=left;
if(arr[right]>=arr[max]&&right<=n)max=right;
if(max!=i)
{
max_value=arr[max];
arr[max]=arr[i];
arr[i]=max_value;
heapify(arr,n,max);
}
}
// 构造大顶堆
void build(vector<int>& arr,int n)
{
if(n<1)return;
for(int i=(n+1)/2-1;i>=0;i--)
{
heapify(arr,n,i);
}
}
//堆排序
void heapsort(vector<int>& arr)
{
int n=arr.size()-1;
for(int i=n;i>0;i--)
{
build(arr,i);
int max=arr[0];
arr[0]=arr[i];
arr[i]=max;
}
}
int main()
{
vector<int> arr={1,3,2,6,4,7,5,10,9};
heapsort(arr);
for(int i=0;i<arr.size();i++)
{
cout<<arr[i]<<endl;
}
}
二、快速排序
基本思想:
通过一趟排序将待排数组分隔成独立的两部分,左边一部分均比基准值小,右边一部分均比基准值大,分别对这两部分记录继续进行排序,以达到整个序列有序。
实现过程:
①设置左右指针low、high,初始值分别为数组起始序号、末尾序号;设置基准值key,默认基准值为数组第一位,即第一位为空。
②从后面开始向前搜索(high--),找到第一个小于key的arr[high],就将arr[high]赋给arr[low],此时序号为high的位置为空;此时从前面开始向后搜索(low++),找到第一个大于key的arr[low],就将arr[low]赋给arr[high],此时序号为low的位置为空。
③重复步骤②,直到low=high,则将基准值插入该位置,此时基准左边全部小于基准值,右边全部大于基准值。
#include <iostream>
#include <vector>
using namespace std;
// 快速排序
void quicksort(vector<int>& arr,int i,int j) // arr为待排序数组,i和j分别为左边界和右边界
{
if(i>=j)return; //递归结束条件
int low=i,high=j,key=arr[low]; //low和high为左右指针,key为基准,现在可以看做low的位置是空的
while(low<high)
{
while(low<high&&arr[high]>key) //从右到左,寻找比基准小的数
{
high--;
}
if(low<high)
{
arr[low]=arr[high];
}
while(low<high&&arr[low]<key) //从左到右,寻找比基准大的数
{
low++;
}
if(low<high)
{
arr[high]=arr[low];
}
}
arr[low]=key; //当前low=high,左边全部小于基准,右边全部大于基准,因此在该位置插入基准值
quicksort(arr,i,low-1);
quicksort(arr,low+1,j);
}
int main()
{
vector<int> arr={1,3,2,6,5,4,10,9,8};
quicksort(arr,0,arr.size()-1);
for(int i=0;i<arr.size();i++)
{
cout<<arr[i]<<" ";
}
return 0;
// for(auto value:arr)
// {
// cout<<value<<" ";
// }
}
三、冒泡排序
基本思想:
重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
实现过程:
①比较相邻的元素。如果第一个比第二个大,就交换他们两个。对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
②不计最后一个元素,重复步骤①,直到第一个元素。
③重复步骤②,直到第一个元素结束,此时数组升序。
#include<iostream>
#include<vector>
using namespace std;
void bubblesort(vector<int>& arr)
{
int mark,n=arr.size()-1;
for(int i=n;i>0;i--)
{
mark=0;
for(int j=0;j<i;j++)
{
if(arr[j+1]<arr[j])
{
mark=1;
swap(arr[j+1],arr[j]);
}
}
if(mark==0)return;
}
}
int main()
{
vector<int> arr={1,3,6,4,5,2,9,4};
bubblesort(arr);
for(int i=0;i<arr.size();i++)
{
cout<<arr[i]<<" ";
}
}
四、选择排序
实现过程:
①从未排序元素中寻找最小元素,放到已排序序列的末尾。
②重复步骤①,直到所有元素均排序完毕。
#include<iostream>
#include<vector>
using namespace std;
void selectsort(vector<int>& arr)
{
int min;
for(int i=0;i<arr.size();i++)
{
min=i;
for(int j=i+1;j<arr.size();j++)
{
if(arr[j]<arr[min])min=j;
}
swap(arr[min],arr[i]);
}
}
int main()
{
vector<int> arr={1,5,6,8,2,3,0,5};
selectsort(arr);
for(int i=0;i<arr.size();i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
五、插入排序
实现过程:
①将待排序序列前一部分元素看做一个有序序列,把之后的元素当成是未排序序列。
②从头到尾依次扫描未排序序列,将每个元素插入有序序列的适当位置。
#include<iostream>
#include<vector>
using namespace std;
void insertsort(vector<int>& arr)
{
int value,i,j;
for(i=1;i<arr.size();i++)
{
value=arr[i];
for(j=i-1;j>=0&&value<arr[j];j--)
{
arr[j+1]=arr[j];
}
arr[j+1]=value;
}
}
int main()
{
vector<int> arr={1,0,5,2,4,9,2,7};
insertsort(arr);
for(int i=0;i<arr.size();i++)
{
cout<<arr[i]<<" ";
}
}