![img](https://www.runoob.com/wp-content/uploads/2019/03/sort.png)
冒泡排序
每次把最大的数移到后面
void bubbleSort(vector<int>& vc,int n){
for(int i=0;i<n;i++){
for(int j=0;j<n-i-1;j++){
if(vc[j]>vc[j+1])swap(vc[j],vc[j+1]);
}
}
}
选择排序
每次把最小的数放到前面
void selectionSort(vector<int>& vc,int n){
for(int i=0;i<n;i++){
int index = i;
for(int j=i;j<n;j++){
if(vc[index]>vc[j])index = j;
}
swap(vc[index],vc[i]);
}
}
插入排序
插入到前面排序的末尾,大的数往后移
void insertionSort(vector<int>& vc,int n){
for(int i=1;i<n;i++){
int key = vc[i];
int j = i - 1;
while(j>=0 && key < vc[j]){
vc[j+1] = vc[j];
j--;
}
vc[j+1] = key;
}
}
希尔排序
先将整个数组分成多块,使用插入排序对每块排序,然后将块大小增大块数量减少再每块排序,直到块数量为1
void shellSort(vector<int>& vc,int n){
int h = 1;
while(h < n / 3)h = h * 3 + 1;
while(h >= 1){
for(int i = h;i<n;i++){
int j = i;
while(j >= h && vc[j] < vc[j - h]){
swap(vc[j],vc[j-h]);
j -= h;
}
}
h /= 3;
}
}
归并排序
基于分治,先分开,再合并
void merge(vector<int>&vc,int l,int r,int mid){
vector<int>tmp(r - l + 1);
for(int k = l; k <= r; k++)tmp[k-l] = vc[k];
int i = l, j = mid + 1;
for(int k = l; k <= r; k++){
if(i > mid){
vc[k] = tmp[j - l];
j++;
}
else if(j > r){
vc[k] = tmp[i - l];
i++;
}
else if(tmp[i - l] < tmp[j - l]){
vc[k] = tmp[i - l];
i++;
}
else{
vc[k] = tmp[j - l];
j++;
}
}
}
void merge_Sort(vector<int>& vc,int l,int r){
if(l >= r)return ;
int mid = (l + r) >> 1;
merge_Sort(vc,l,mid);
merge_Sort(vc,mid+1,r);
merge(vc,l,r,mid);
}
void mergeSort(vector<int>& vc,int n){
merge_Sort(vc,0,n-1);
}
快速排序
以第一个点为基准,大的放后面,小的放前面,之后将第一个点放在中间可以将两个范围区分开
void Quick_Sort(vector<int>& vc,int l,int r){
if(l >= r)return ;
int i = l, j = r, tmp = vc[l];
while(i!=j){
while(vc[j] >= tmp && i < j)j--;
while(vc[i] <= tmp && i < j)i++;
if(i < j)swap(vc[i], vc[j]);
}
vc[l] = vc[i];
vc[i] = tmp;
Quick_Sort(vc, l, i-1);
Quick_Sort(vc, i+1, r);
}
void QuickSort(vector<int>& vc,int n){
Quick_Sort(vc,0,n-1);
}
堆排序
先建堆,形成大顶堆,然后将最大的值放到最后,堆个数-1,然后再将堆调整成大顶堆,以此循环,直到堆个数剩1不用交换。
void heapadjust(vector<int>& vc,int i,int n){//调整堆
int l = i * 2 + 1, r = i * 2 + 2;
int tmp = i;
if(i < n/2) {//保证不是叶子节点
if(l < n && vc[l] > vc[tmp]) tmp = l;
if(r < n && vc[r] > vc[tmp]) tmp = r;
if(tmp != i){
swap(vc[i],vc[tmp]);
heapadjust(vc, tmp, n);
}
}
}
void heapbuild(vector<int>& vc,int n){//建堆
for(int i = n / 2 - 1; i >= 0; i--){
heapadjust(vc,i,n);
}
}
void heapSort(vector<int>& vc,int n){
heapbuild(vc,n);
for(int i = n - 1; i > 0; i--){
swap(vc[0],vc[i]);
heapadjust(vc,0,i);
}
}
计数排序
先存下个数,然后从小往后将元素加到数组里,空间换时间。
void countingSort(vector<int>& vc,int n){
int maxx = INT_MIN, minx = INT_MAX;
for(int i = 0;i < n; i++){
maxx = max(maxx, vc[i]);
minx = min(minx, vc[i]);
}
vector<int>cnt(maxx - minx + 1, 0);
for(int i = 0; i < n; i++){
cnt[vc[i] - minx]++;
}
int index = 0;
for(int i = 0; i <= maxx - minx ;i++){
while(cnt[i]--){
vc[index++] = i + minx;
}
}
}
桶排序
计数排序的进阶,每个桶可以存放多个不同元素。基于分治算法,将每个元素分到对应的桶,同一个桶使用链表排序,最后再合并。
const int BUCKET_NUM = 10;
struct ListNode{
int val;
ListNode* next;
ListNode():val(0), next(nullptr){}
ListNode(int _val):val(_val), next(nullptr){}
ListNode(int _val,ListNode* _next):val(_val), next(_next){}
};
ListNode* insert(ListNode* head, int val) {//桶内插入一个数
ListNode* newNode = new ListNode(val);
if(!head)return newNode;
ListNode* head1 = new ListNode();
ListNode* pre = head1;
ListNode* cur = head;
pre ->next = cur;
while(cur && cur -> val <= val){
pre = cur;
cur = cur->next;
}
newNode -> next = cur;
pre -> next = newNode;
return head1 -> next;
}
ListNode* merge(ListNode* head1, ListNode* head2){//两个桶进行合并
ListNode* head = new ListNode();
ListNode* pre = head;
while(head1 && head2){
if(head1 -> val <= head2 -> val){
pre -> next = head1;
head1 = head1 -> next;
}
else{
pre -> next = head2;
head2 = head2 -> next;
}
pre = pre ->next;
}
if(head1) pre -> next = head1;
if(head2) pre -> next = head2;
return head -> next;
}
void BucketSort(vector<int>& vc,int n){
vector<ListNode* >buckets(BUCKET_NUM,nullptr);
for(int i = 0; i < n; i++){
int index = vc[i] / BUCKET_NUM;
buckets[index] = insert(buckets[index], vc[i]);
}
ListNode* head = buckets[0];
for(int i = 1; i < BUCKET_NUM ; i++){
head = merge(head , buckets[i]);
}
for(int i = 0; i < n; i++){
vc[i] = head -> val;
head = head -> next;
}
}
基数排序
从个位开始对数组进行排序,依次往后,同一位数相等的两个数前面位数不等大的肯定放在后面,所以放的时候肯定还是放在后面,因为是从后面先取放在后面。
int maxbit(vector<int>vc, int n){//计算最大位数
int d = 1, p = 10;
for(int i = 0; i < n; i++){
while(vc[i] >= p){
d++;
p *= 10;
}
}
return d;
}
void radixSort(vector<int>& vc,int n){
int d = maxbit(vc,n),radix = 1;
vector<int>tmp(n);
vector<int>cnt(10);
for(int i = 1; i <= d ;i++){//进行d次,从个位开始
for(int j = 0; j < 10; j++)cnt[j]=0;
for(int j = 0; j < n; j++){
int k = vc[j] / radix % 10;
cnt[k]++;
}
for(int j = 1; j < 10; j++)cnt[j] = cnt[j] + cnt[j-1];//算出每个桶放置最后面的位置
for(int j = n - 1; j >= 0; j--){
int k = vc[j] / radix % 10;
tmp[cnt[k] - 1] = vc[j];
cnt[k]--;
}
for(int j = 0; j < n; j++)vc[j] = tmp[j];
radix *= 10;
}
}