七大排序(简洁明了,注释分明,思路清晰)

七大排序

不废话,直接上代码,注释分明,思路清晰。

sortingmethod.h

#ifndef SORTINGMETHOD_H
#define SORTINGMETHOD_H

#include <iostream>

#define SORTTYPE int

using namespace std;

/**
 * insert sort
 */
/*direct insert sort*/
void direct_insert_sort( SORTTYPE *arr,int len);

/*shell sort*/
void shell_sort(SORTTYPE *arr,int len);


/**
 * select sort
 */
/*simple select sort*/
void simple_select_sort( SORTTYPE *arr ,int len);

/*heap sort*/
void heap_sort(SORTTYPE *arr,int len);
void adjust_max_heap(SORTTYPE *arr, int len,int i);
void build_max_heap(SORTTYPE *arr , int len);


/**
 * exchange sort
 */
/*bubble sort*/
void bubble_sort( SORTTYPE *arr ,int len);

/*fast sort*/
void quick_sort(SORTTYPE *arr , int start, int end);





/**
 * merge sort
 */
void merge_merge_sort(SORTTYPE *arr , int first, int mid ,int last , SORTTYPE *temp);
void devide_merge_sort(SORTTYPE *arr , int first, int last , SORTTYPE *temp);
void merge_sort(SORTTYPE *arr, int len);


/*show element*/
void show_element(SORTTYPE *arr , int len);

#endif // SORTINGMETHOD_H

sortingmethod.cpp


#include "sortingmethod.h"


/*
 * All sorting is from min to max
 */

/**
 * insert sort
 */
/*direct insert sort*/
void direct_insert_sort( SORTTYPE *arr,int len){

    int temp ,i=0,j=0;              /*temp暂存arr[i]*/

    for(i = 1 ; i < len ; i++){
        /*对每一个arr[i]~arr[0]的数*/
        temp = arr[i];
        for(j=i ; j>0 ; j -- ) {

            /*当arr[j-1]比tem大时,向右移动一个位置*/
            if ( arr[j-1] > temp ){
                arr[j] = arr[j-1];
            }
            else
                break;
        }

        /*此时j刚好为重复的那个数字*/
        arr[j] = temp;
    }

//    for(i = 1; i<len ; i++){
//        temp = arr[i];
//        for(j = i-1 ; j > -1 ; j--){
//            if(arr[j]>temp){
//                arr[j+1] = arr [j];
//            }
//            else
//                break;
//        }
//        arr[j+1] = temp;
//    }

}

/*shell sort*/
void shell_sort(SORTTYPE *arr,int len){
    /*
     * 将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;
     * 每次将gap折半减小,循环上述操作;
     * 当gap=1时,利用直接插入,完成排序。
     */
    int i=0,j=0,k=-1,temp=-1;
    int gap = len / 2;      /*初始化gap,一般时len的一半*/

    while( gap >= 1  ){

        for( i = gap ; i < len ; i+=gap ){
            k = i; temp = arr[k];
            for( j = i - gap ; (j >= 0)&&(arr[j] >temp); j -=gap ){
                arr[j+gap] = arr[j];
                k = j;
            }
            arr[k] = temp;
        }
        gap /=2;
    }

}

/**
 * select sort
 */
/*simple select sort*/
void simple_select_sort( SORTTYPE *arr ,int len){
    /*
      简单选择排序的基本思想:比较+交换。
        从待排序序列中,找到关键字最小的元素;
        如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;
        从余下的 len - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束。
        因此简单选择排序也是通过两层循环实现。
            第一层循环:依次遍历序列中的每一个元素
            第二层循环:将遍历得到的当前元素依次与余下的元素进行比较,符合最小元素的条件,则交换。
    */
    int i=0,j=0,k=0,min,tem;
    for(i=0; i < len ; i++ ){
        min = arr[i];
        /*下面这个循环找到本轮的最小值和下标*/
        for(j = i+1 ; j < len ; j++){
            if(arr[j] < min){
                min = arr[j];
                k = j;
            }
        }

        /*如果arr[i]>min则需要交换*/
        if(arr[i] > min){
           tem= arr[i];
           arr[i] = arr[k];
           arr[k] = tem;
        }

    }



}

/*heap sort*/
   /*
    堆排序按照以下步骤完成:

    1.首先将序列构建称为大顶堆;
    (这样满足了大顶堆那条性质:位于根节点的元素一定是当前序列的最大值

    2.取出当前大顶堆的根节点,将其与序列末尾元素进行交换;
    (此时:序列末尾的元素为已排序的最大值;由于交换了元素,当前位于根节点的堆并不一定满足大顶堆的性质)

    3.对交换后的n-1个序列元素进行调整,使其满足大顶堆的性质;

    4.重复2.3步骤,直至堆中只有1个元素为止
    */


/* 调整大顶堆 */
void adjust_max_heap(SORTTYPE *arr, int len,int i){
    /*
     * arr:待调整序列
     * len: 序列长度
     * i:需要调整的结点
     */

    /*定义一个int值保存当前序列最大值的下标*/
    int largest = i; int left,right;

    /*执行循环操作任务:1.寻找最大值的下标;2.最大值与父节点交换*/
    while (1) {
        /*获得序列左右叶子节点的下标*/
        left = i*2+1; right = i*2+2;

        /*当左叶子节点的下标小于序列长度 并且 左叶子节点的值大于父节点时,将左叶子节点的下标赋值给largest*/
        if(left < len  && arr[left] > arr[largest]){
            largest = left;
        }else{
            largest = i;
        }

        /*当右叶子节点的下标小于序列长度 并且 右叶子节点的值大于父节点时,将右叶子节点的下标值赋值给largest*/
        if(right < len && arr[right] > arr[largest])
            largest = right;

        /*如果largest不等于i 说明当前的父节点不是最大值,需要交换值*/
        int temp;
        if(largest != i){
            temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;
            i = largest;
            continue;
        }else{
            break;
        }
    }
}
/*建立大顶堆*/
void build_max_heap(SORTTYPE *arr , int len){
    for( int i = (len-1)/2; i>-1; i-- ){
        adjust_max_heap(arr,len,i);
    }
}

/* 堆排序  heap_sort */
void heap_sort(SORTTYPE *arr,int len){
    /*先建立大顶堆,保证最大值位于根节点;并且父节点的值大于叶子结点*/
    build_max_heap(arr , len);

    /* i = 当前堆中序列的长度.初始化为序列的长度*/
    int i = len;

    /*执行循环:1. 每次取出堆顶元素置于序列的最后(len-1,len-2,len-3...)
              2. 调整堆,使其继续满足大顶堆的性质,注意实时修改堆中序列的长度*/
    int temp;
    while( i > 0){
        temp = arr[i-1];
        arr[i - 1] = arr[0];
        arr[0] = temp;
        /*堆中序列长度减1*/
        i-=1;
        /*调整大顶堆*/
        adjust_max_heap(arr , i , 0);
    }
}



/**
 * exchange sort
 */
/*bubble sort*/
void bubble_sort( SORTTYPE *arr ,int len){
    int temp;

    for(int i =0 ; i < len ; i++ ){
        for(int j = len-1; j>i ; j --){
            if (arr[j] < arr[j-1]){
                temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp;
            }
        }
    }

}

/*quick sort*/
void quick_sort(SORTTYPE *arr ,int start,int end){
    /*快速排序的基本思想:挖坑填数+分治法
        从序列当中选择一个基准数(pivot ,这里选择序列当中第一个数最为基准数)
        将序列当中的所有数依次遍历,比基准数大的位于其右侧,比基准数小的位于其左侧
        重复步骤1.2,直到所有子集当中只有一个元素为止。
        用伪代码描述如下:
        1.i =left; j = right; 将基准数挖出形成第一个坑a[i]。
        2.j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。
        3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。
        4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中
     */


    int i, j ,pivot;
    if (start <end){
        i = start;
        j = end;
        pivot = arr[start];
    }
    else
        return;             /*注意这个地方容易忘*/

    while(i < j){

        /*从右开始向左寻找第一个小于pivot的值*/
        while(i < j && arr[j] >= pivot)
            j-=1;

        /*将小于pivot的值移到左边*/
        if(i < j){
            arr[i] = arr[j];
            i+=1;
        }

        /*从左开始向右寻找第一个大于pivot的值*/
        while (i < j && arr[i] <= pivot)
            i+=1;

        /*将大于pivot的值移到右边*/
        if(i<j){
            arr[j] = arr[i];
            j-=1;
        }
    }

    /*循环结束后,说明 i=j,此时左边的值全都小于pivot,右边的值全都大于pivot*/
    arr[i]=pivot;

    show_element(arr,14);
    /*pivot的位置移动正确,那么此时只需对左右两侧的序列调用此函数进一步排序即可*/
    /*递归调用函数:依次对左侧序列:从0 ~ i-1//右侧序列:从i+1 ~ end*/
    quick_sort(arr,start,i-1);

    cout<<"left is all right"<<endl;
    quick_sort(arr,i+1,end);
}


/**
 * merge sort
 */
/*
 *  merge_sort
 * 归并排序的函数
 */
void merge_sort(SORTTYPE *arr,int len){
    /*
    归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个典型的应用。
    它的基本操作是:
        将已有的子序列合并,达到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

    归并排序要做两件事:
        分解----将序列每次折半拆分
        合并----将划分后的序列段两两排序合并
    因此,归并排序实际上就是两个操作,拆分+合并

    如何合并?
    arr[first...mid]为第一段,arr[mid+1...last]为第二段,并且两端已经有序,现在要将两端合成达到arr[first...last]并且也有序。

    (1)依次从第一段与第二段中取出元素比较,将较小的元素赋值给temp[]
    (2)重复执行上一步,当某一段赋值结束,则将另一段剩下的元素赋值给temp[]
    (3)此时将temp[]中的元素复制给arr[],则得到的arr[first...last]有序

    如何分解?
    (1)采用递归的方法,首先将待排序列分成A,B两组;
    (2)重复对A、B序列分组;
    (3)直到分组后组内只有一个元素,此时认为组内所有元素有序,分组结束。
    */

    SORTTYPE  temp[len];
    /*调用归并排序*/
    devide_merge_sort(arr, 0 , len-1 , temp);

}
void merge_merge_sort(SORTTYPE *arr , int first, int mid , int last , int *temp){

    /*合并的函数----将序列arr[first...mid]与序列arr[mid+1...last]进行合并*/
    int i = first, j = mid +1 ,k = 0;

    /*当左右两边都有数时进行比较,取较小的数*/
    while(i <= mid && j <= last){
        if( arr[i] <= arr[j])
            temp[k++] = arr[i++];
        else
            temp[k++] = arr[j++];
    }

    /*如果左边序列还有数*/
    while(i <= mid)
        temp[k++] = arr[i++];

    /*如果右边序列还有数*/
    while(j <= last)
        temp[k++] = arr[j++];

    /*将temp当中该段有序元素赋值给L待排序列使之部分有序*/
    for(int x = 0; x < k ; x++)
        arr[first + x] = temp[x];

}
/*这是分组的函数*/
void devide_merge_sort(SORTTYPE *arr , int first, int last , SORTTYPE *temp){
    int mid;
    if(first < last){
        mid = (first + last)/2;

        /*使左边序列有序*/
        devide_merge_sort(arr, first ,mid ,temp);

        /*使右边序列有序*/
        devide_merge_sort(arr, mid+1 , last ,temp);

        /*将两个有序序列合并*/
        merge_merge_sort(arr, first ,mid , last,temp);
        show_element(arr , 14);
    }
}



/*show element*/
void show_element(SORTTYPE *arr , int len){
    for(int i = 0; i < len ; i++ ){
        SORTTYPE tem = arr[i];
        cout<<tem<<"   ";
    }
    cout<<'\n';
}

main.cpp

#include <iostream>

#include "sortingmethod.h"

using namespace std;

int main()
{
    SORTTYPE arr[] = {8,1,13,7,3,12,4,6,2,14,5,9,11,10};
    int len = 14;
    show_element(arr, len);

//    direct_insert_sort(arr,len);

//    bubble_sort(arr , len);

//    shell_sort(arr,len);

//    simple_select_sort(arr,len);

//    heap_sort(arr , len);

//    quick_sort(arr,0,13);

//    merge_sort(arr,len);

   cout<<"sort ending!"<<endl;
    show_element(arr, len);

    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值