不定类型长度的排序系统【+各类排序算法详解】(C++实现)


创作不易,如果以下内容对你有帮助,别忘了点一个赞,让更多的小伙伴能看到吧~~


排序算法详情

一 、冒泡排序

  • 原理

    冒泡排序算法的基本原理就是比较相邻两个数字的大小。将两个数中比较大的那个数交换到靠后的位置,不断交换下去就可以将最大的那两个数放到队列的尾部。然后重头再次交换)(交换list.lenght-1次),直到将数列排成有序数列。

  • 时间复杂度(平均): O(n^2)

  • 时间复杂度(最坏): O(n^2)

  • 时间复杂度(最好): O(n)

  • 空间复杂度: O(1)

  • 稳定性: 稳定

  • 代码实现

    /*
    函数功能: 冒泡排序
    函数名称: bubbleSort
    参数: arr -- 传入数组指针
          len -- 数组长度
    返回值: void
    */
    template<typename T>
    void bubbleSort(T *arr, int len)
    {
        T temp;
        if(len <= 1)
            return;
        for(int i=0;i<len-1;i++)
        {
            for(int j=0;j<len-i-1;j++)
            {
                if(arr[j]>arr[j+1])
                {
                    swap(arr,j, j+1);
                }
            }
        }
    }
    

二、插入排序

  • 原理:

    插入排序首先将数列分为两部分,数列的第一数为left,其余数位right部分。然后将right部分中的数逐一取出,插入到left部分的适当位置。当right部分为空时,left部分就成了一个有序的序列。

  • 时间复杂度(平均): O(n^2)
  • 时间复杂度(最坏): O(n^2)
  • 时间复杂度(最好): O(n)
  • 空间复杂度: O(1)
  • 稳定性: 稳定
  • 代码实现:
    /*
    函数功能: 插入排序
    函数名称: insertSort
    参数: arr -- 传入数组指针
         len -- 数组长度
    返回值: void
    */
    template<typename T>
    void insertSort(T *arr, int len)
    {
        T temp;
        int j;
        if(len <= 1)
            return;
        for(int i=1; i<len;i++)
        {
            j = i;
            while(j>0)
            {
                if(arr[j] < arr[j-1])
                {
                    swap(arr, j, j-1);
                    j--;
                }else{
                    break;
                }
            }
        }
    }
    

三、选择排序

  • 原理:

    选择排序从数列中选择最大(最小)的那个数,将这个数放到合适的位置。然后抛开这个数的子序列中找最大(最小)的那个数放到合适的位置。然后一直到子序列为空。

  • 时间复杂度(平均): O(n^2)
  • 时间复杂度(最坏): O(n^2)
  • 时间复杂度(最好): O(n^2)
  • 空间复杂度: O(1)
  • 稳定性: 不稳定
  • 代码实现:
    /*
    函数功能: 选择排序
    函数名称: selectSort
    参数: arr -- 传入数组指针
          len -- 数组长度
    返回值: void
    */
    template<typename T>
    void selectSort(T *arr, int len)
    {
        T temp;
        int j, min_index;
        if(len <= 1)
            return;
        for(int i=0; i<len; i++)
        {
            min_index = i;
            for(j=i+1;j<len;j++)
            {
                if(arr[j]<arr[min_index])
                    min_index = j;
            }
            swap(arr, min_index, i);
        }
    }
    

四、希尔排序

  • 原理:

    改进了得插入排序,将待排序的数组根据差量分成若干的的子数组,分别进行插入排序,通过不断地修改组距,使得分组数逐渐减少,当组距为1是,就是一个插入排序。

  • 时间复杂度(平均): O(n^1.3)

  • 时间复杂度(最坏): O(n^2)

  • 时间复杂度(最好): O(n)

  • 空间复杂度: O(1)

  • 稳定性: 不稳定

  • 代码实现

    /*
    函数功能: 希尔排序算法
    函数名称: shellSort
    参数: arr -- 传入数组指针
          len -- 数组长度
    返回值: void
    */
    template<typename T>
    void shellSort(T *arr, int len)
    {
        if(len <= 1)
            return;
        T temp;
        int j, gap = len/2;
        while(gap > 0)
        {
            for(int i=gap; i<len;i++)
            {
                j = i;
                while(j>0)
                {
                    if(arr[j] < arr[j-gap])
                    {
                        swap(arr,j,j-gap);
                        j -= gap;
                    }else{
                        break;
                    }
                }
            }
            gap /= 2;
        }
    }
    

五、快速排序

  • 原理:

    快速排序是先从数据序列中选一个元素,并将序列中所有比该元素小的元素都放到它的右边或左边,再对左右两边分别用同样的方法处之直到每一个待处理的序列的长度为1,处理结束。

  • 时间复杂度(平均): O(nlog2n)
  • 时间复杂度(最坏): O(n^2)
  • 时间复杂度(最好): O(nlog2n)
  • 空间复杂度: O(nlog2n)
  • 稳定性: 不稳定
  • 代码实现:
    /*
    函数功能: 具体实现快速排序算法
    函数名称: quickSort_code
    参数: arr -- 传入数组指针
          strat -- 数组起始下标
          strat -- 数组结尾下标
    返回值: void
    */
    template<typename T>
    void quickSort_code(T *arr, int strat, int end)
    {
    	// strat是数组的开始,将start作为基数
    	int m = arr[strat];
        // 递归结束条件
    	if (strat >= end)
    		return;
    	int i = strat, j = end;
    	while (i != j)
    	{
    		while (j > i&&arr[j] >= m)
    		{
    			j--;
    		}
    		swap(arr,i, j);
    		while (j > i&&arr[i] <= m)
    		{
    			i++;
    		}
    		swap(arr,i,j); 
    	}
    	quickSort_code(arr, strat, i - 1);
    	quickSort_code(arr, i + 1, end);
    }
    
    /*
    函数功能: 调用快速排序算法,保持所有排序参数一致性
    函数名称: quickSort
    参数: arr -- 传入数组指针
          len -- 数组长度
    返回值: void
    */
    template<typename T>
    void quickSort(T *arr, int len)
    {
        if(len <= 1)
            return;
        quickSort_code(arr, 0, len-1);
    }
    

六、归并排序

  • 原理:

    该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。将两个有序表合并成一个有序表。

  • 时间复杂度(平均): O(nlog2n)
  • 时间复杂度(最坏): O(nlog2n)
  • 时间复杂度(最好): O(nlog2n)
  • 空间复杂度: O(n)
  • 稳定性: 稳定
  • 代码实现:
    /*函数功能: 合并两个有序数组
    函数名称: merge_achieve
    参数: arr -- 传入数组指针
          start -- 数组起始下标
          mid -- 数组中间下标
          end -- 数组结尾下标
    返回值: void
    */
    template<typename T>
    void merge_achieve(T *arr, int start, int mid, int end)
    {
        int n1 = mid - start + 1;
        int n2 = end - mid;
        T *left = new T[n1];
        T *right = new T[n2];
    
        // int left[n1], right[n2];
        int i, j, k;
    
        for (i = 0; i < n1; i++)
            left[i] = arr[start+i];
        for (j = 0; j < n2; j++)
            right[j] = arr[mid+1+j];
    
        i = j = 0;
        k = start;
        while (i < n1 && j < n2)
            if (left[i] < right[j])
                arr[k++] = left[i++];
            else
                arr[k++] = right[j++];
    
        while (i < n1) /* left[] is not exhausted */
            arr[k++] = left[i++];
        while (j < n2) /* right[] is not exhausted */
            arr[k++] = right[j++];
    }
    
    
    /*函数功能: 具体实现归并排序算法
    函数名称: merge
    参数: arr -- 传入数组指针
          start -- 数组起始下标
          end -- 数组结尾下标
    返回值: void
    */
    template<typename T>
    void merge(T *arr, int start, int end) // 先排序,再合并
    {
        int mid;
        if (start < end)
        {
            mid = (start + end) / 2;
            merge(arr, start, mid); // 递归划分原数组左半边array[start...mid]
            merge(arr, mid+1, end); // 递归划分array[mid+1...end]
            merge_achieve(arr, start, mid, end); // 合并
        }
    }
    
    /*函数功能: 调用归并排序算法
    函数名称: mergeSort
    参数: arr -- 传入数组指针
          len -- 数组长度
    返回值: void
    */
    template<typename T>
    void mergeSort(T *arr, int len)
    {
        // 调用归并排序函数
        merge(arr, 0, len-1);
    }
    

七、基数排序(桶排序)

  • 原理:

    基数排序算法的基本原理是将待排序的数组中的值,按照位数上的值作大小比较,排序后存入对应角标范围为0-9的桶中。每个位数比较排序后,依次从不为空的桶中取出值合并,成为一个部分排序后新的数组,作为更高位数排序的原始数组,直到最终排序完成。

  • 时间复杂度(平均): O(d(r+n))
  • 时间复杂度(最坏): O(d(rd+n))
  • 时间复杂度(最好): O(d(r+n))
  • 空间复杂度: O(rd+n)
  • 稳定性: 稳定
  • 代码实现:
    /*函数功能: 基数排序(桶排序)算法
    函数名称: radixSort
    参数: arr -- 传入数组指针
          len -- 数组长度
    返回值: void
    */
    template<typename T>
    void radixSort(T *arr, int len)
    {
        if(len <= 1)
            return;
        int i, base = 1;
        T max = arr[0];
        // 求最大数
        for(int i=1; i<len;i++)
        {
            if(arr[i] > max)
                max = arr[i];
        }
        // 动态分配内存,存储桶中取出的数字
        int *t = new int[len];
    
    
        while (max/base>0)
        {
            int bucket[10] = {0};
            // 统计每个桶中数的个数
            for(i=0; i<len; i++)
            {
                bucket[arr[i] / base % 10]++;
            }
            // 累加每个桶的个数
            for(i=1;i<10; i++)
            {
                bucket[i] += bucket[i-1];
            }
            // 根据每个数对应的bucket的数作为下标,指定一次桶排新数组
            for(i=len-1; i>=0; i--)
            {
                t[bucket[arr[i] / base % 10] - 1] = arr[i];
                // 考虑一个桶有多个数字,取出一次减1
                bucket[arr[i] / base % 10] --;
            }
            // 更新原数组
            for(i=0; i<len; i++)
            {
                arr[i] = t[i];
            }
    
            base = base * 10;
        }
        delete []t;
    }
    

八、堆排序

  • 原理:

    将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的 n-1 个序列重新构造成一个堆,这样就会得到 n 个元素中次大的值。如此反复执行,得到一个有序序列。

  • 时间复杂度(平均): O(nlog2n)
  • 时间复杂度(最坏): O(nlog2n)
  • 时间复杂度(最好): O(nlog2n)
  • 空间复杂度: O(1)
  • 稳定性: 不稳定
  • 代码实现:
    /*函数功能: 对数组进行堆化
    函数名称: heapify
    参数: tree -- 传入数组指针
          n -- 数组长度
          i -- 堆化的数组下标值
    返回值: void
    */
    
    template<typename T>
    void heapify(T tree[], int n , int i)
    {
        if (i >= n)
            return;
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;
        int max = i;
        if(c1 < n && tree[c1] > tree[max])
            max = c1;
        if(c2 < n && tree[c2] > tree[max])
            max = c2;
        if(max != i)
        {
            swap(tree, max,i);
            heapify(tree, n, max);
        }
    }
      
    /*函数功能: 创建二叉堆树
    函数名称: build_heap
    参数: tree -- 传入数组指针
          n -- 数组长度
    返回值: void
    */
    
    template<typename T>
    void build_heap(T tree[], int n)
    {
        // 完全二叉树的叶子节点=非叶子节点-1
        int last_node = n-1;
        int parent = (last_node-1)/2;
        for(int i=parent; i >= 0; i--)
            heapify(tree, n, i);
    }
    
    
    /*函数功能: 堆排序算法
    函数名称: heapSort
    参数: arr -- 传入数组指针
          len -- 数组长度
    返回值: void
    */
    
    template<typename T>
    void heapSort(T *arr, int len)
    {
        build_heap(arr, len);
        for(int i = len - 1; i >= 0; i--)
        {
            swap(arr,i,0);
            heapify(arr, i, 0);
        }
    }
    

排序系统详情

一、功能展示

在这里插入图片描述

二、源码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章