基本排序算法

一. 冒泡排序(BubbleSort)
基本思想:两个数比较大小,较大的数下沉,较小的数冒起来。
过程:
比较相邻的两个数据,如果第二个数小,就交换位置。
从后向前两两比较,一直到比较最前两个数据。最终最小数被交换到起始的位置,这样第一个最小数的位置就排好了。
继续重复上述过程,依次将第2.3…n-1个最小数排好位置。

public static void BubbleSort(int [] arr){
     int temp;//临时变量
     for(int i=0; i<arr.length-1; i++){   //表示趟数,一共arr.length-1次。
         for(int j=arr.length-1; j>i; j--){

             if(arr[j] < arr[j-1]){
                 temp = arr[j];
                 arr[j] = arr[j-1];
                 arr[j-1] = temp;
             }
         }
     }
 }

二. 选择排序(SelctionSort)
基本思想:
在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换;
。。。
第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。

public static void select_sort(int array[],int lenth){

   for(int i=0;i<lenth-1;i++){

       int minIndex = i;
       for(int j=i+1;j<lenth;j++){
          if(array[j]<array[minIndex]){
              minIndex = j;
          }
       }
       if(minIndex != i){
           int temp = array[i];
           array[i] = array[minIndex];
           array[minIndex] = temp;
       }
   }
}

三. 插入排序(Insertion Sort)
基本思想:
在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

for(i=1;i<n;i++){
            /**
             * temp为本次循环待插入有序列表中的数
             */
            int temp = a[i];
            /**
             * 寻找temp插入有序列表的正确位置
             */
            for(j=i-1;j>=0 && a[j]>temp;j--){
                /**
                 * 元素后移,为插入temp做准备
                 */
                a[j+1] = a[j];
            }
            /**
             * 插入temp
             */
            a[j+1] = temp;
            print(a,n,i);
        }

四. 希尔排序(Shell Sort)
在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序。
然后逐渐将增量减小,并重复上述过程。直至增量为1,此时数据序列基本有序,最后进行插入排序。

public static void shell_sort(int array[],int lenth){

   int temp = 0;
   int incre = lenth;

   while(true){
       incre = incre/2;

       for(int k = 0;k<incre;k++){    //根据增量分为若干子序列

           for(int i=k+incre;i<lenth;i+=incre){

               for(int j=i;j>k;j-=incre){
                   if(array[j]<array[j-incre]){
                       temp = array[j-incre];
                       array[j-incre] = array[j];
                       array[j] = temp;
                   }else{
                       break;
                   }
               }
           }
       }

       if(incre == 1){
           break;
       }
   }
}

五. 快速排序(Quicksort)
快速排序有三种实现方式
实现方式一:左右指针法
算法思想:在待排序序列中选择一个数据作为基准值(暂且将区间右端数据作为基准值),定义两个指针left,right开始分别指向待排序区间的两端,左指针向右找比基准值大的数据,找到后停下来,接着右指针向左开始找比基准值小的数据,找到后停下来,交换左右指针所指数据,直到两指针相遇,出循环后将左指针指向的值与基准值进行交换,交换成功后比基准值小的数据都在其左边,比基准值大的数据都在基准值的右边,换言之基准值已经处于合适的位置。接着递归对基准值的左区间和右区间进行排序,区间只有一个数据默认已经有序。

先从数列中取出一个数作为key值;
将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
对左右两个小数列重复第二步,直至各区间只有1个数。

//左右指针法
int PartSort1(int* a, int left, int right)//左右指针法
{
    int mid = GetMidIndex(a, left, right);
    QSwap(&a[mid], &a[right]);

    int key = a[right];//用区间的最右边的值作为基准值
    int keyidx = right;
    while (left <right)
    {
        while (left < right && a[left] <= key)
            ++left;
        while (left < right && a[right] >= key)
            --right;
        if (a[left] != a[right])
            QSwap(&a[left], &a[right]);
    }
    QSwap(&a[left], &a[keyidx]);
    return left;
}

//递归实现
void QuickSort1(int* a, int left,int right)//递归实现
{
    assert(a);
    if (left < right)
    {
        int div = PartSort1(a, left, right);

        QuickSort1(a, left, div-1);//递归左区间
        QuickSort1(a, div+1, right);//递归右区间
    }
}

实现方式二:挖坑法
算法思想:在待排序序列中选择一个数据作为基准值(暂且将区间右端数据作为基准值),首次将坑设在基准值处,定义两个指针left,right开始分别指向待排序区间的两端,左指针向右找比基准值大的数据,找到后将该值填入坑中并且将坑的位置更新在左指针所指位置,接着右指针向左开始找比基准值小的数据,找到后将该值填入坑中并且将坑的位置更新在右指针所指位置,直到两指针相遇,出循环后比基准值小的数据都在其左边,比基准值大的数据都在基准值的右边,换言之基准值已经处于合适的位置。接着递归对基准值的左区间和右区间进行排序,区间只有一个数据默认已经有序。

public static void quickSort(int a[],int l,int r){
     if(l>=r)
       return;

     int i = l; int j = r; int key = a[l];//选择第一个数为key

     while(i<j){

         while(i<j && a[j]>=key)//从右向左找第一个小于key的值
             j--;
         if(i<j){
             a[i] = a[j];
             i++;
         }

         while(i<j && a[i]<key)//从左向右找第一个大于key的值
             i++;

         if(i<j){
             a[j] = a[i];
             j--;
         }
     }
     //i == j
     a[i] = key;
     quickSort(a, l, i-1);//递归调用
     quickSort(a, i+1, r);//递归调用
 }

算法实现3:前后指针法
算法思想:在待排序序列中选择一个数据作为基准值(暂且将区间右端数据作为基准值),定义两个指针prev和cur,cur首次指向待排序区间的第一个元素,prev指向cur的前一个位置,只要cur没走到区间末尾,就在中间找比基准值小的数据,每找到一次将prev++,然后如果二者所指元素不同就将其所指元素交换,直到cur走到区间的最右端退出循环,之后将prev++,将cur和prev所指的数据进行交换。至此基准值被排序到正确位置,赌鬼其左右区间即可完成整个排序。

六. 归并排序(Merge Sort)
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。
首先考虑下如何将2个有序数列合并。这个非常简单,只要从比较2个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

//将有序数组a[]和b[]合并到c[]中
void MemeryArray(int a[], int n, int b[], int m, int c[])
{
 int i, j, k;

 i = j = k = 0;
 while (i < n && j < m)
 {
     if (a[i] < b[j])
         c[k++] = a[i++];
     else
         c[k++] = b[j++]; 
 }

 while (i < n)
     c[k++] = a[i++];

 while (j < m)
     c[k++] = b[j++];
}

七. 堆排序(HeapSort)

比较当前父节点是否大于子节点,如果大于就交换,直到一趟建堆完成~

   /**
     * 建堆
     *
     * @param arrays          看作是完全二叉树
     * @param currentRootNode 当前父节点位置
     * @param size            节点总数
     */
    public static void heapify(int[] arrays, int currentRootNode, int size) {

        if (currentRootNode < size) {
            //左子树和右字数的位置
            int left = 2 * currentRootNode + 1;
            int right = 2 * currentRootNode + 2;

            //把当前父节点位置看成是最大的
            int max = currentRootNode;

            if (left < size) {
                //如果比当前根元素要大,记录它的位置
                if (arrays[max] < arrays[left]) {
                    max = left;
                }
            }
            if (right < size) {
                //如果比当前根元素要大,记录它的位置
                if (arrays[max] < arrays[right]) {
                    max = right;
                }
            }
            //如果最大的不是根元素位置,那么就交换
            if (max != currentRootNode) {
                int temp = arrays[max];
                arrays[max] = arrays[currentRootNode];
                arrays[currentRootNode] = temp;

                //继续比较,直到完成一次建堆
                heapify(arrays, max, size);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值