八个经典排序算法总结

1、插入排序

原理:插入排序顾名思义将当先元素插入到其本应在的位置,其他的元素依次向后移(自己实现的时候忘记了移动元素),如下动图所示。时间复杂度:O(n^{^{2}}),这里是最大时间复杂度,有些时候时间复杂度会大大降低(高度有序序列的情况下)。

template <typename T>
void insertSort(T arr[],int n){
    for(int i = 0;i < n;i++){
        int temp = arr[i];
        int j = i;
        for(;arr[j-1] > temp&&j >= 1;j--){
            //记住这里还要有移位操作
            arr[j] = arr[j-1];
        }
        std::swap(arr[j],temp);
    }
}

2、选择排序

每次选择最大的元素作为当前位置的元素。时间复杂度O(n^{^{2}})

算法原理:

  1. 首先选择最大(小)的元素放在序列的第一位
  2. 在剩余的元素中选择最大(小)的元素凡在齐次
  3. 重复1、2直到完全有序
template <typename T>
void bubbleSort(T arr[],int n){
    int j,min;
    for(int i = 0;i < n;i++){
        min = i;
        for(j = i + 1;j < n;j++){
            if(arr[min] > arr[j])
                min = j;
        }
        std::swap(arr[i],arr[min]);
    }
}

3、冒泡排序

算法原理:按大小交换相邻两个元素的顺序,每一次排序就会确定一个最大(小)值

template <typename T>
void bubbleSort(T arr[],int n){
    for(int i = 0;i < n;i++){
        for(int j = 0;j < n-i-1;j++){
            if(arr[j] > arr[j+1])
                std::swap(arr[j],arr[j+1]);
        }
    }
}

4、归并排序(稳定nlogn,但需要额外内存)

1、递归

void __merge(T arr[], int l, int mid, int r){

    // 经测试,传递aux数组的性能效果并不好
    T aux[r-l+1];
    for( int i = l ; i <= r; i ++ )
        aux[i-l] = arr[i];

    int i = l, j = mid+1;
    for( int k = l ; k <= r; k ++ ){

        if( i > mid )
        { arr[k] = aux[j-l];
            j ++;
        }
        else if( j > r ){//一定要else if
            arr[k] = aux[i-l];
            i ++;
        }
        else if( aux[i-l] < aux[j-l] )
        { arr[k] = aux[i-l];
            i ++;
        }
        else
        { arr[k] = aux[j-l];
            j ++;
        }
    }
}
void mergesort(int arr[],int l,int r){
    if(l >= r)
        return;
    int mid = l + (r-l)/2;
    mergesort(arr,l,mid);
    mergesort(arr,mid+1,r);
    _merge(arr,l,mid,r);

}

2、非递归

void mergesort(int arr[],int n){
    for(int sz = 1;sz < n;sz += sz)
        for(int i = 0;i + sz -1< n;i += sz+sz){
            _merge(arr,i,i+sz-1,min(n-1,i+sz+sz-1));
        }
}

5、DFS算法

滑雪问题:

int skidfs(int map[][],bool mark[][],int i,int j,int n){
    int k;
    if(mark[i][j])
        return mark[i][j];
    if(map[i][j] > map[i-1][j] && i - 1 >= 0){
        k = skidfs(map,mark,i-1,j,n) + 1;
        if(k > mark[i][j])
            mark[i][j] = k;
    }
    if(map[i][j] > map[i][j-1] && j - 1 >= 0){
        k = skidfs(map,mark,i,j-1,n) + 1;
        if(k > mark[i][j])
            mark[i][j] = k;
    }
    if(map[i][j] > map[i+1][j] && i + 1 <= n){
        k = skidfs(map,mark,i+1,j,n) + 1;
        if(k > mark[i][j])
            mark[i][j] = k;
    }
    if(map[i][j] > map[i][j+1] && j + 1 <= 0){
        k = skidfs(map,mark,i,j+1,n) + 1;
        if(k > mark[i][j])
            mark[i][j] = k;
    }
    return mark[i][j];
}
void skisolution(int n){
    int output = 0;
    int step = 1;
    int map[n][n];
    int mark[n][n] = {0};
    //bool mark[n][n] = {false};//最开始使用的是true的方式来记录点有没有被访问过但是对于
    //本题不适用,因为同一个可能要被访问多次
    for(int i = 0;i < n;i++){
        for(int j = 0;j < n;j++){
            step = skidfs(map,mark,i,j,n);
            if(step > output)
                output = step;
        }
    }
    std::cout<<output<<std::endl;
}

 dfs算法步骤:

1.1、有单一起点的:

int main(){
    dfs();
}

1.2、多种可能起点的:

int main(){
    for:
        for:
            dfs();
}
void dfs(){
    //终止条件判断1、最小路径需要判断是否最小了2、如果需要打印路径这里判断是否到终点,到终点后打印操作
    //不超越边界or没被访问过、操作过;
        dfs();
        //有时候在归来的时候需要去除标记
}

5、迷宫路径问题

int rows = 5,cols = 6;
int count = 0;
int map[5][6] = {{0,1,0,0,0,1},{0,0,0,1,0,0},{1,0,1,0,0,1},{1,0,0,1,0,1},{1,1,0,0,0,0}};
bool mark[5][6] = {false};
stack<pair<int,int>> stk;
void dfs(int x,int y){
    int index[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
    if(x == rows-1 && y == cols-1){
        stack<pair<int,int>> temp;
        cout << "******************path"<< ++count <<  "******************" << endl;
        while(!stk.empty()){
            pair<int,int> pt = stk.top();
            stk.pop();
            temp.push(pt);
        }
        while(!temp.empty()){
            pair<int,int> p2 = temp.top();//栈是先进后出,但是打印的得时候是从上往下打印的也就是说,先进的就会在下面
            temp.pop();
            cout<<"("<<p2.first<<","<<p2.second<<")"<<endl;
            stk.push(p2);
        }
        return;
    }
    for(int i = 0;i < 4;i++){
        int ix = x + index[i][0];
        int iy = y + index[i][1];
        if(ix >= 0&&ix != rows&&iy >=0&&iy != cols&&mark[ix][iy] == false&&map[ix][iy] == 0){
            mark[ix][iy] = true;
            stk.push(make_pair(ix,iy));
            dfs(ix,iy);
            mark[ix][iy] = false;
            stk.pop();
        }
    }
}
int main(){
    dfs(0,0);
    cout<<"completed"<<endl;
    stack<int> a;
    for(int i =0;i<10;i++){
        a.push(i);
    }
    while(!a.empty()){
        cout<<a.top()<<endl;
        a.pop();
    }
}

以上过程中dfs后有一个回溯的过程:stk.pop();是因为等遇到错的路径的时候要回到根路径

6、快速排序(双路快排)

void quicksort(int a[],int l,int r){
    int temp = a[l];
    int i = l,j = r;
    if(l > r){
        return;
    }
    while(i!=j){
        while(i<j&&a[j] >= temp)//这里右边的一定要在前
            j--;
        while(i < j&&a[i] <= temp)
            i++;
        if(i < j){
            swap(a[i],a[j]);
        }
    }
    swap(a[l],a[i]);
    quicksort(a,l,i-1);
    quicksort(a,i+1,r);
}
int main()
{
    int n =10;
    int arr[10] = {2,1,4,5,1,2,5,8,10,11};
    quicksort(arr,0,n-1);
    for(int i = 0;i < n;i++){
        cout<<arr[i]<<endl;
    }
}

7、堆排序

void shiftdown(int arr[],int n,int k){
    while(2*k+1 < n){
        int j = 2*k +1;
        if(j + 1 < n &&arr[j + 1] > arr[j])
        //最小堆的话就是if(j + 1 < n &&arr[j + 1] < arr[j])
            j = j + 1;
        if(arr[k] > arr[j])
        //if(arr[k] < arr[j])
            break;
        swap(arr[k],arr[j]);
        k = j;
    }
}
void heapsort(int arr[],int n){
    //heapfiy process
    for(int i = n/2;i >= 0;i--)
        shiftdown(arr,n,i);
    for(int i = n -1;i > 0;i--){
        swap(arr[0],arr[i]);
        shiftdown(arr,i,0);
    }
}
using namespace std;
typedef struct node
{
    int value;
    DNode* Dleft;
    DNode* Dright;
} DNode;

DNode* head = NULL;
DNode* createDL(int value){
    DNode* head = (DNode*)malloc(sizeof(DNode));
    head->value = value;
    head->Dleft = head->Dright = head;
}
DNode* insert(int index,int val){
    if(index == 0){
        DNode* tempnode = (DNode*)malloc(sizeof(DNode));
        if(!tempnode)
            return -1;
        tempnode->Dleft = head;
        tempnode->Dright = head->Dright;
        head->Dright->Dleft = tempnode;
        head->Dleft = tempnode;
    }
    int i = 0;
    DNode *pnode = head;
    while(i < index){
        pnode = pnode->Dleft;
        i++;
    }
    DNode* newnode = (DNode*)malloc(sizeof(DNode));
    newnode->Dleft = pnode->Dleft;
    newnode->Dright = pnode;
    pnode->Dleft->Dright = newnode;
    pnode->Dleft = newnode;A

}

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值