zoukankan      html  css  js  c++  java
  • 排序算法总结

    1 冒泡排序

    排序思想:每次选出最大的放到序列末尾,序列每次去除最后的元素,直到剩下最后一个元素排序结束。

    特点:在寻找本轮最大元素时可以设置一个标志位,如果一轮下来标志位没变说明所有元素都以有序。平均时间复杂度为O(n^2)。

    2 插入排序

    排序思想:在对第i个元素进行添加时,前面i-1个元素已经排序结束,将第i个元素插入到前面i-1个元素的适当位置即可。

    特点:当元素基本有序时只需要做比较和少量的换序即可。平均时间复杂度为O(n^2)。

    递归实现的代码:

    template<class T>
    void insert_sort(T A[],int n){
      if(n<1)
        return;
      insert_sort(A,n-1); 

      int a = A[n];
      int k = n-1;
      while(k>=0 &&A[k]>a){
        A[k+1] = A[k];
        k = k-1;
      }
      A[k+1] = a; // k+1恰好是空出那个元素
    }

    3 归并排序

    排序思想:长度为N的序列可以分为两个长度为N/2的序列,如果两个长度为N/2的序列已经有序,那么使用合并算法【见附录】合并即可,这样问题的规模就减小为两个长度为N/2序列的排序问题,递归即可。

    特点:平均时间复杂度为O(n*logn)。

    4 选择排序

    排序思想:每次从待排序数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

    特点: 选择排序是不稳定的排序方法,平均时间复杂度为O(n^2)。

    5 堆排序

    排序思想:使用待排序数据建立一个堆,堆是这样一种数据结构:所有父节点数据均大于(或小于)子节点数据。这样每次取出根节点即可获得有序序列。

    特点:堆排序没有使用额外的存储空间!!平均时间复杂度是O(n^2)。

    附录:

    合并算法:

    template <class Type>
    void merge(Type A[],int p,int q,int r)
    {
        Type *bp = new Type[r-p+1];  //这种方式的缺点就是需要开辟较大的内存空间!
        int i=p,j=1+q,k=0;
       
       
        while (i<=q && j<=r)
            if(A[i] <= A[j])
                bp[k++] = A[i++];
            else
                bp[k++] = A[j++];
           
            if(i==q+1)  //这里必须注意写法,不能使用< 判断,因为最后停留的位置不能确定,但是这个条件能确定
                for(;j<=r;j++)
                    bp[k++] = A[j];
                else
                    for (;i<=q;i++)
                        bp[k++] = A[i];
                   
                    k=0;
                    for (i=p;i<=r;i++)
                        A[i] = bp[k++];
                   
                    delete bp;
    }

    堆操作:

    1 元素上移:

    void shift_up(int H[],int i){
        int value = H[i];
        int pos = i;
        while(i/2 >= 1 && value > H[i/2]){
            pos = i/2;
            H[i] = H[i/2];
            i = i/2;
        }
        H[pos] = value;
    }

    2 元素下移:

    void shift_down(int H[],int n,int i){
      int value = H[i];
      bool flag = false;
      int pos = i;
      while(i*2 <= n){
        int j;
        if(i*2 == n)  //一定要判断数组是否越界
          j = i*2;
        else
          j = H[2*i] >= H[2*i+1] ? 2*i :2*i + 1;
        if(value<H[j]){
          pos = j;
          H[i] = H[j];
          i = j;
        }else{ //停止查找
          break;
        }
      }
      H[pos] = value;  //最终的位置!
    }

    3 元素插入:

    void insert(int H[],int &n,int value){  //注意这里n要使用引用变量
        n = n+1;
        H[n] = value;
        shift_up(H,n);
    }

    4 元素删除

    void delete_i(int H[],int &n,int i){
        value = H[i];
        last = H[n];
        n = n - 1;
        H[i] = last;
        if(last > value)
            shift_up(H,i);
        else
            shift_down(H,n,i);   
    }

    5 删除堆顶元素

    int delete_max(int H[],int &n){
        int max = H[1];
        delete_i(H[],n,1);
        return max;
    }

    堆建立:

    void make_heap(int A[],int H[],int n){
        int num = 0;
        for(i=0;i<n;i++){
            insert(H,num,A[i]);
        }
    }

    void make_heap_self(int H[],int n){   
        A[n] = A[0];  //这个比较特殊。。
        for(i = n/2;i>=1;i--){
            shift_down(H,n,i);
        }
    }

    堆排序:

    void heap_sort(int A[],int n){
      int i;
      make_heap_self(A,n);
      for(i=n;i>1;i--){
        swap(A,i,1);
        shift_down(A,i-1,1);
      }
    }

  • 相关阅读:
    Linux基础命令---sudo
    Linux基础命令---yes
    Linux基础命令---shutdown
    Divide Two Integers
    java 判断两个数是否异号
    字节顺序的详细解释(转)
    java无符号移位(>>>)和有符号移位(>>)
    java 参数化类型
    c++事件内核对象(event)进程间激活(转)
    windows多线程编程(一)(转)
  • 原文地址:https://www.cnblogs.com/guojidong/p/2825388.html
Copyright © 2011-2022 走看看