zoukankan      html  css  js  c++  java
  • 各排序算法的Java实现及简单分析

    一,直接插入排序

        //直接插入排序的算法时间复杂度分析:
        //如果输入为正序,则每次比较一次就可以找到元素最终位置,复杂度为O(n)
        //如果输入为反序,则每次要比较i个元素,复杂度为O(n2)
        //平均时间复杂度为O(n2)
        public static void straigthInsertSort(int[] num)
        {
            int n = num.length;
            for(int i = 1;i < n;i++)//从第二个开始向前插入
            {
                int x = num[i];
                int j;
                for(j = i - 1;j >= 0&&num[j] > x;j--)
                {
                    num[j + 1] = num[j];
                }
                num[j + 1] = x;
                print(num);
            }
        }
        //    5 2 2 3 6 2 0 8 9 9 
        //    2 5 2 3 6 2 0 8 9 9 
        //    2 2 5 3 6 2 0 8 9 9 
        //    2 2 3 5 6 2 0 8 9 9 
        //    2 2 3 5 6 2 0 8 9 9 
        //    2 2 2 3 5 6 0 8 9 9 
        //    0 2 2 2 3 5 6 8 9 9 
        //    0 2 2 2 3 5 6 8 9 9 
        //    0 2 2 2 3 5 6 8 9 9 
        //    0 2 2 2 3 5 6 8 9 9 

    二,希尔排序

        //希尔排序的时间负责度与增量的选取有关,每次折半的增量选取时间复杂度为O(n2),最佳时间复杂度为O(nlogn)
        //希尔排序没有快排快,中等规模条件下表现较好,大规模情况下不如快排
        //快排在最坏情况下表现极差,而希尔在最坏情况下和平均情况表现差不多
        //希尔每趟排序会让序列变得更加有序,虽然下一趟元素个数增多,但是需要移动的增加并不是很多,因此效率比直接插入高很多
        //希尔排序适合于大多数情况
        public static void ShellSort(int[] num)
        {
            int n = num.length;
            int d = n;
            while(d != 1)
            {
                d = d / 2;
                for(int x = 0;x < d;x++)
                {
                    for(int i = x + d;i < n;i = i + d)
                    {
                        int tmp = num[i];
                        int j;
                        for(j = i - d;j >= 0&&num[j] > tmp;j = j - d)
                            num[j + d] = num[j];
                        num[j + d] = tmp;
                    }
                }
                print(num);
            }
        }
    //    6 8 8 5 5 1 1 2 0 8 
    //    1 1 2 0 5 6 8 8 5 8 
    //    1 0 2 1 5 6 5 8 8 8 
    //    0 1 1 2 5 5 6 8 8 8 

    三,选择排序

        //选择排序的时间复杂度是O(n2)
        //因为需要进行数据的交换操作,所以选择排序算法是不稳定的
        //选择排序每趟结束都有一个元素在最终位置上
        public static void selectSort(int[] num)
        {
            int n = num.length;
            for(int i = 0;i < n;i++)
            {
                int cur = num[i];
                int key = i;//最小值的索引
                for(int j = i + 1;j < n;j++)
                    if(num[j] < num[key])
                        key = j;
                if(key != i)
                {
                    num[i] = num[key];
                    num[key] = cur;
                }
                print(num);
            }
        }
    //    0 6 1 0 9 4 8 0 2 3 
    //    0 6 1 0 9 4 8 0 2 3 
    //    0 0 1 6 9 4 8 0 2 3 
    //    0 0 0 6 9 4 8 1 2 3 
    //    0 0 0 1 9 4 8 6 2 3 
    //    0 0 0 1 2 4 8 6 9 3 
    //    0 0 0 1 2 3 8 6 9 4 
    //    0 0 0 1 2 3 4 6 9 8 
    //    0 0 0 1 2 3 4 6 9 8 
    //    0 0 0 1 2 3 4 6 8 9 
    //    0 0 0 1 2 3 4 6 8 9 

    四,冒泡排序

        //冒泡排序的时间复杂度为O(n2)
        //冒泡排序上稳定的算法
        //每趟结束都有一个元素在最终位置上
        public static void bubbleSort(int[] num)
        {
            int n = num.length;
            for(int i = 0;i < n - 1;i++)
            {
                for(int j = 0;j < n - i - 1;j++)
                {
                    if(num[j] > num[j + 1])
                    {
                        int tmp = num[j];
                        num[j] = num[j + 1];
                        num[j + 1] = tmp;
                    }
                }
                print(num);
            }
        }
    //    4 0 8 3 4 2 9 7 8 4 
    //    0 4 3 4 2 8 7 8 4 9 
    //    0 3 4 2 4 7 8 4 8 9 
    //    0 3 2 4 4 7 4 8 8 9 
    //    0 2 3 4 4 4 7 8 8 9 
    //    0 2 3 4 4 4 7 8 8 9 
    //    0 2 3 4 4 4 7 8 8 9 
    //    0 2 3 4 4 4 7 8 8 9 
    //    0 2 3 4 4 4 7 8 8 9 
    //    0 2 3 4 4 4 7 8 8 9 

    五,快速排序

        //快排的时间复杂度为O(nlogn)
        //当n较大时用快排比较好,当序列基本有序时,用快排反而不太好
        //快排是不稳定的
        //快排被认为是相同时间复杂度下平均性能最好的排序算法
        public static void quickSort(int[] num)
        {
            quick(num,0,num.length - 1);
        }
        
        private static void quick(int[] num,int low,int high)
        {
            if(low < high)//!
            {
                int mid = partition(num, low, high);
                print(num);
                quick(num,low,mid - 1);
                quick(num,mid + 1,high);
            }
        }
        
        private static int partition(int[] num,int low,int high)
        {
            int temp = num[low];
            while(low < high)
            {
                while(num[high] >= temp&&high > low)
                    high--;
                num[low] = num[high];
                while(num[low] <= temp&&high > low)
                    low++;
                num[high] = num[low];
            }
            num[low] = temp;
            return low;
        }
    //    3 2 6 5 8 4 6 9 2 2 
    //    2 2 2 3 8 4 6 9 5 6 
    //    2 2 2 3 8 4 6 9 5 6 
    //    2 2 2 3 8 4 6 9 5 6 
    //    2 2 2 3 6 4 6 5 8 9 
    //    2 2 2 3 5 4 6 6 8 9 
    //    2 2 2 3 4 5 6 6 8 9 

    六,堆排序

        //堆排序的时间复杂度是O(nlogn)
        //堆排序是不稳定的排序算法
        //由于初始建堆时比较的次数较多,所以堆排序不适合于记录较少的情况
        public static void heapSort(int[] num)
        {
            int n = num.length;
            for(int i = (n - 1) / 2;i >= 0;i--)
                heapAdjust(num, i, n);
            for(int i = 0;i < n;i++)
            {
                int tmp = num[0];
                num[0] = num[n - 1 - i];
                num[n - 1 - i] = tmp;
                print(num);
                heapAdjust(num, 0, n - 1 - i);
            }
        }
        
        private static void heapAdjust(int[] num,int s,int size)
        {
            int tmp = num[s];
            int child;
            while(s < size)
            {
                child = s * 2 + 1;
                if(child < size - 1&&num[child] < num[child + 1])
                    child++;
                if(child >= size||num[s] > num[child])
                    break;
                num[s] = num[child];
                s = child;
                num[child] = tmp;
            }
        }
    //    5 7 7 6 0 6 4 0 1 4 
    //    0 6 7 5 4 6 4 0 1 7 
    //    1 6 6 5 4 0 4 0 7 7 
    //    0 5 6 1 4 0 4 6 7 7 
    //    0 5 4 1 4 0 6 6 7 7 
    //    0 4 4 1 0 5 6 6 7 7 
    //    0 1 4 0 4 5 6 6 7 7 
    //    0 1 0 4 4 5 6 6 7 7 
    //    0 0 1 4 4 5 6 6 7 7 
    //    0 0 1 4 4 5 6 6 7 7 
    //    0 0 1 4 4 5 6 6 7 7 

    七,归并排序

        
        //归并排序是稳定的排序算法
        //归并排序的时间复杂度是O(nlogn)
        //归并排序的速度仅次于快速排序,适用于总体无序但个子项相对有序的情况
        public static void mergeSort(int[] num)
        {
            int n = num.length - 1;
            mergeRecursive(num, 0, n);
        }
        
        private static void mergeRecursive(int[] num,int left,int right)
        {
            if(left < right)
            {
                int middle = (left + right) / 2;
                mergeRecursive(num, left, middle);
                mergeRecursive(num, middle + 1, right);
                merge(num,left,middle,right);
            }
        }
        
        private static void merge(int[] num,int left,int middle,int right)
        {
            int[] tmp = new int[num.length];
            int mid = middle + 1;
            int index = left;
            int originLeft = left;
            while(left <= middle&&mid <= right)
            {
                if(num[left] < num[mid])
                    tmp[index++] = num[left++];
                else
                    tmp[index++] = num[mid++];
            }
            while(left <= middle)
                tmp[index++] = num[left++];
            while(mid <= right)
                tmp[index++] = num[mid++];
            while(originLeft <= right)
                num[originLeft] = tmp[originLeft++];
            print(num);
        }
    //    5 7 7 8 2 0 5 0 3 4 
    //    5 7 7 8 2 0 5 0 3 4 
    //    5 7 7 8 2 0 5 0 3 4 
    //    5 7 7 2 8 0 5 0 3 4 
    //    2 5 7 7 8 0 5 0 3 4 
    //    2 5 7 7 8 0 5 0 3 4 
    //    2 5 7 7 8 0 0 5 3 4 
    //    2 5 7 7 8 0 0 5 3 4 
    //    2 5 7 7 8 0 0 3 4 5 
    //    0 0 2 3 4 5 5 7 7 8 
  • 相关阅读:
    最小生成树之算法记录【prime算法+Kruskal算法】【模板】
    [LC] 90. Subsets II
    [LC] 19. Remove Nth Node From End of List
    [LC] 125. Valid Palindrome
    [LC] 127. Word Ladder
    [LC] 102. Binary Tree Level Order Traversal
    [LC] 5. Longest Palindromic Substring
    [LC] 167. Two Sum II
    [LC] 437. Path Sum III
    [LC] 94. Binary Tree Inorder Traversal
  • 原文地址:https://www.cnblogs.com/YLsY/p/5778690.html
Copyright © 2011-2022 走看看