大家好,我又来啦。研究生的苦逼生活让我很少有时间学习算法(孩子心里苦),在导师压榨下今天抽空给大家写一篇关于时间复杂度为O(N^2)的排序算法及二分查找小总结,后续会继续更新二分及排序的进一步拓展算法。
排序算法
排序算法顾名思义也就是给定一个数组或链表对其中的元素以一定规则进行排序,值得注意的是这里的规则可能是自定义的规则,此乃后话。本次介绍的排序指的是将数组中的元素从小到大进行排序,主要介绍时间复杂度为O(N^2)的排序算法。
选择排序
首先介绍一个经典的排序算法——选择排序。选择排序的原理很简单即在数组的第i(0~N-1)选取该位置到第N-1个位置中最小的数放在该位置并依次遍历该数组。每次迭代过程中均会选择最小的数放在某一位置上因此该算法被称为选择排序。口头叙述较难理解,直接上代码:
#include<bits/stdc++.h>
using namespace std;
void swap(vector<int>&arr,int a,int b){ //交换两数的位置
int tmp;
tmp=arr[a];
arr[a]=arr[b];
arr[b]=tmp;
}
void Selectsort(vector<int>&arr){
for(int i=0;i<arr.size();i++){
int log=i,min=arr[i];
for(int j=i+1;j<arr.size();j++){
if(arr[j]<min){
min=arr[j];
log=j; //记录最小值的位置
}
}
swap(arr,i,log); //将最小值交换到该位置
}
}
int main(){
int n;
cin>>n;
vector<int> arr;
while(n--){
int num;
cin>>num;
arr.push_back(num);
}
Selectsort(arr);
for(int num:arr) cout<<num<<' ';
cout<<endl;
return 0;
}
冒泡排序
冒泡排序模仿的是水中的泡泡会随着上升而不断变大。我们仿照此现象对数组进行遍历若数组左边的数大于右边相邻的数则交换两数的位置,这样循环N次便可将数组元素从小到大排序。啥也不说,上代码:
#include<bits/stdc++.h>
using namespace std;
void swap(vector<int>&arr,int a,int b){ //交换两数的位置
arr[a]=arr[a]^arr[b];
arr[b]=arr[a]^arr[b];
arr[a]=arr[a]^arr[b];
}
void Maopaosort(vector<int>&arr){
for(int i=arr.size()-1;i>=0;i--){
for(int j=0;j<i;j++){
if(arr[j]>arr[j+1]) swap(arr,j,j+1); //相邻两元素交换位置
}
}
}
int main(){
int n;
cin>>n;
vector<int> arr;
while(n--){
int num;
cin>>num;
arr.push_back(num);
}
Maopaosort(arr);
for(int num:arr) cout<<num<<' ';
cout<<endl;
return 0;
}
插入排序
插入排序是时间复杂度为O(N^2)的排序中最重要的,其原理类似于我们日常玩扑克牌,每次抽到牌会根据牌大小插入到相应位置。该算法对数组进行遍历,每遍历到一个位置需保证该位置之前的元素是有序的。不废话了,上代码!
#include<bits/stdc++.h>
using namespace std;
void swap(vector<int>&arr,int a,int b){ //交换两数的位置
arr[a]=arr[a]^arr[b];
arr[b]=arr[a]^arr[b];
arr[a]=arr[a]^arr[b];
}
void Inserctionsort(vector<int>&arr){
for(int i=1;i<arr.size();i++){
for(int j=i-1;j>=0;j--){
if(arr[j]>arr[j+1]) swap(arr,j,j+1); //相邻两元素交换位置
}
}
}
int main(){
int n;
cin>>n;
vector<int> arr;
while(n--){
int num;
cin>>num;
arr.push_back(num);
}
Inserctionsort(arr);
for(int num:arr) cout<<num<<' ';
cout<<endl;
return 0;
}
以上就是今天要介绍的时间复杂度为O(N^2)的排序算法,下面将简单介绍一下二分查找。
二分查找
二分查找每次将数组丢弃一半来查找该数组中是否存在该元素,时间复杂度为O(logN)是一种非常快速的查找算法。一般要求数组是有序,但是在只要能在某种规则下一次将数组丢弃一半均可使用二分查找算法即使是数组无序的情况。下面将介绍经典的二分查找算法,上代码:
#include<bits/stdc++.h>
using namespace std;
void swap(vector<int>&arr,int a,int b){ //交换两数的位置
arr[a]=arr[a]^arr[b];
arr[b]=arr[a]^arr[b];
arr[a]=arr[a]^arr[b];
}
void Inserctionsort(vector<int>&arr){
for(int i=1;i<arr.size();i++){
for(int j=i-1;j>=0;j--){
if(arr[j]>arr[j+1]) swap(arr,j,j+1); //相邻两元素交换位置
}
}
}
int BinarySearch(vector<int>&arr,int num,int l,int r){
while(l<=r){
int mid=(l+r)>>1;
if(arr[mid]>num) r=mid-1;
else if(arr[mid]<num) l=mid+1;
else return mid;
}
return -1;
}
int main(){
int n,m;
cin>>n;
m=n;
vector<int> arr;
while(n--){
int num;
cin>>num;
arr.push_back(num);
}
Inserctionsort(arr);
cout<<BinarySearch(arr,m,0,arr.size()-1)<<endl; //输出目标数在数组中的下标元素
return 0;
}
此外还有两种情况仍可使用二分,第一种是求第一个大于等于某个数的下标,第二种是求无序数组的局部最小值。这两种情况今晚时间有限将不再赘述,想继续了解二分的更多应用及更多有趣的算法可以点赞加关注,让我们共同进步亲人们。