记录排序算法
1、模板化的快排
1.1、快排思路
- 首先,在这个序列中随便找一个数作为基准数,通常为了方便,以第一个数作为基准数m。
- 快速排序其实是冒泡排序的一种改进,冒泡排序每次对相邻的两个数进行比较,这显然是一种比较浪费时间的。
- 而快速排序是分别从两端开始”探测”的,先从右往左找一个小于m的数(哨兵j,最开始指向最右边),再从左往右找一个大于m的数(哨兵i,最开始指向最左边),然后交换他们,直至j<=i;
- 第一轮排序完成后,m左边的数都比它小,右边的数都比它大;
- 然后模拟刚才的方法处理m左边的和右边的序列,直至所有数都归位。
- 快速排序之所以比较快,是因为与冒泡排序相比,每次的交换时跳跃式的,每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。
- 这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。
- 当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(n2),它的平均时间复杂度为O(nlog2n)
1.2、代码
#include<iostream>
#include<string>
using namespace std;
int arr1[10];
string arr2[10];
double arr3[10];
char arr4[10];
template <class T>
void quickSort(T arr[], int s, int e){
if(s > e) return;
T tmp = arr[s];
int i = s;
int j = e;
while(i < j){
while(arr[j] >= tmp && i < j)j--;
while(arr[i] <= tmp && i < j)i++;
if(i < j){
T t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[s] = arr[i];
arr[i] = tmp;
quickSort(arr, s, i-1);
quickSort(arr, i+1, e);
}
template <class T>
void printWant(T arr[], int size){
cout<<"now array:"<<endl;
quickSort(arr, 0, size - 1);
for(int i = 0;i < size; i++)
cout<<arr[i]<<"\t";
cout<<endl<<"end";
}
int main(){
cout<<"1:int\t2:string\t3:double\t4:char\nplease choice = ";
int choice;cin>>choice;
while(choice != -1){
cout<<"input order array size = ";
int size;cin>>size;
cout<<"array:";
switch(choice){
case 1:
for(int i = 0;i < size; i++)cin>>arr1[i];
printWant(arr1, size);
break;
case 2:
for(int i = 0;i < size; i++)cin>>arr2[i];
printWant(arr2, size);
break;
case 3:
for(int i = 0;i < size; i++)cin>>arr3[i];
printWant(arr3, size);
break;
case 4:
for(int i = 0;i < size; i++)cin>>arr4[i];
printWant(arr4, size);
break;
default:
cout<<"input err,please input once again!"<<endl;
}
cout<<"\nagain choice = ";
cin>>choice;
}
}
1.3、效果
2、插入排序
2.1思路
- 将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。
- 双层循环:外层是排序次数n-1,内层循环表示的是每一趟排序的数字。
- 时间复杂度O(n2)
2.2代码
#include<iostream>
using namespace std;
int a[10];
void insert_sort(int a[], int size){
for(int i = 0;i < size; i++)
for(int j = i+1;j < size; j++){
if(a[i] > a[j]){
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
void print_want(int a[], int size){
for(int i = 0;i < size; i++)cout<<a[i]<<"\t";
cout<<"\nsort end";
}
int main(){
cout<<"array size:";
int size;cin>>size;
for(int i = 0;i < size; i++)cin>>a[i];
insert_sort(a,size);
print_want(a,size);
return 0;
}
2.3效果
3、STL sort排序【与结构体结合使用】
3.1、思路
algorithm头文件是个好东西
3.2、代码
#include<iostream>
#include<algorithm>
using namespace std;
int a[10];
struct Point{
int x,y;
};
bool cmpA(int p, int q){
return p>q;
}
bool cmpB(Point m, Point n){
return m.x>n.x;
}
bool cmpC(Point m, Point n){
if(m.x == n.x)
return m.y>n.y;
else return m.x>n.x;
}
int main(){
Point point[10];
cout<<"size:";
int size;cin>>size;
if(size % 2 == 0){
cout<<"array:";
for(int i = 0;i < size; i++)cin>>a[i];
}
else{
cout<<"struct array:";
for(int i = 0;i < size; i++)cin>>point[i].x >>point[i].y;
}
cout<<"choice 1&2:array\tchoice 3&4:struct"<<endl;
int choice;cin>>choice;
switch(choice){
case 1:sort(a, a+size);cout<<"inc:";break;
case 2:sort(a, a+size, cmpA);cout<<"desc:";break;
case 3:sort(point, point+size, cmpB);cout<<"sort:";break;
case 4:sort(point, point+size, cmpC);cout<<"sort:";break;
default:cout<<"no such sort choice."<<endl;
}
if(size%2 == 0)for(int i = 0;i < size; i++)cout<<a[i]<<"\t";
else for(int i = 0;i < size; i++)cout<<point[i].x<<"\t"<<point[i].y<<endl;
return 0;
}
3.3、效果
一个示例:
4、堆排序
4.1、思路
- 是一种选择排序
- 堆:完全二叉树
- 构建初始堆O(n)+交换堆顶元素和末尾元素并重建堆【堆顶元素与末尾元素进行交换,使末尾元素最大/小】
- 升序采用大顶堆,降序采用小顶堆
- 最坏,最好,平均时间复杂度均为O(nlogn)
- 是不稳定排序
4.2、 代码
#include<iostream>
using namespace std;
int a[20];//asc big
void heap_sort(int a[], int s, int e){
int cur = s;
int l = cur*2 + 1;
int tmp = a[cur];
for(;l < e; l = l*2+1){
if(l+1 < e && a[l] < a[l+1])l++;
if(a[l] > tmp){
a[cur] = a[l];
cur = l;
}
else break;
}
a[cur] = tmp;
}
void heap_sort1(int a[], int s, int e){
int cur = s;
int l = cur*2 + 1;
int tmp = a[cur];
for(;l < e; l = l*2+1){
if(l+1 < e && a[l] > a[l+1])l++;
if(a[l] < tmp){
a[cur] = a[l];
cur = l;
}
else break;
}
a[cur] = tmp;
}
int main(){
cout<<"size:";
int size;cin>>size;
cout<<"array:";
for(int i = 0;i < size; i++)cin>>a[i];
cout<<"choice 1&Max\t2&Min:\n";
int choice;cin>>choice;
if(choice == 1){
for(int i = size/2-1;i >= 0; i--)heap_sort(a, i, size-1); //构造最大堆
cout<<"build heapMax:\n";
}else if(choice == 2){
for(int i = size/2-1;i >= 0; i--)heap_sort1(a, i, size); //构造最小堆
cout<<"build heapMin:\n";
}
for(int i = 0;i < size; i++)cout<<a[i]<<"\t";
cout<<endl;
if(choice == 1){
for(int i = size-1; i >= 0; i--){ //交换+调整堆保证a[i-1]是a[0...i-1]中最大
swap(a[0], a[i]);
heap_sort(a, 0, i);
}
}else if(choice == 2){
for(int i = size-1; i >= 0; i--){ //交换+调整堆保证a[i]是a[i...size-1]中最小
swap(a[i], a[0]);
heap_sort1(a, 0, i-1);
}
}else cout<<"choice err"<<endl;
cout<<"after sort:\n";
for(int i = 0;i < size; i++)cout<<a[i]<<"\t";
}
4.3、 效果
5、冒泡排序
- 比较两个相邻的元素,将值大的元素交换到后面
- 有序时-》最好复杂度O(n)
- 时间复杂度O(n2)
#include<iostream>
using namespace std;
int a[10];
int main(){
int size;cin>>size;
for(int i = 0;i <size; i++)cin>>a[i];
for(int i = 0;i < size; i++){
for(int j = i+1;j < size; j++){
if(a[i] > a[j]){
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
for(int i = 0;i < size; i++)cout<<a[i]<<"\t";
}