七种常用排序算法

七种常用排序算法

一、常见排序算法一览:

时间复杂度: 是一个函数,它定量描述了该算法的运行时间。

空间复杂度:一个算法在运行过程中临时占用存储空间大小的量度。

稳定性:保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同就稳定,反之不稳定。

视觉直观感受 7 种常用的排序算法

二、算法C#实现:

1、 直接插入排序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        /*
        具体算法描述如下:
        1.从第一个元素开始,该元素可以认为已经被排序
        2.取出下一个元素,在已经排序的元素序列中从后向前扫描
        3.如果该元素(已排序)大于新元素,将该元素移到下一位置
        4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
        5.将新元素插入到该位置后
        6.重复步骤2~5
        */
        public static void InsertSort(int[] List)
        {
            int tmp = 0;
            int len = List.Length;
            int i = 0;
            int j = 0;

            for (i = 1; i < len; i++)
            {
                tmp = List[i];
                for (j = i - 1; j >= 0; j--)
                {
                    if (tmp < List[j])
                    {
                        List[j + 1] = List[j];
                    }
                    else if (tmp > List[j])
                    {
                        break;
                    }
                }
                List[j + 1] = tmp;
            }
            return;
        }

        static void Main(string[] args)
        {
            int[] intArr = {10, 2, 56, 12, 6, 78, 34, 23, 9, 18, 7};

            InsertSort(intArr);

            for (int k = 0; k < intArr.Length; k++)
            Console.WriteLine(intArr[k]);
            Console.ReadKey();
        }
    }
}

2、 希尔排序

实际上是分组的插入排序。缩小增量排序。先取定一个小于n的整数d1作为第一个增量,把表的全部记录分成d1个组,所有距离为d1的倍数的记录放在同一个组中,在各组内进行直接插入排序;然后,取第二个增量d2(<d1),重复上述的分组和排序,直至所取的增量dt=1。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        public static void ShellSort(int[] List)
        {
            int tmp = 0;
            int len = List.Length;
            int i = 0;
            int j = 0;
            int d = len / 2; /* 初始步长取数组长度的一半 */

            /* 观察看如果d=1的话,即是普通的插入排序算法 */
            while (d >= 1)
            {
                /* 把距离为 d 的元素编为一个组,扫描所有组 */
                for (i = d; i < len; i++)
                {
                    tmp = List[i];

                    for (j = i - d; j >= 0; j = j - d)
                    {
                        if (tmp < List[j])
                        {
                            List[j + d] = List[j];
                        }
                        else if (tmp > List[j])
                        {
                            break;
                        }
                    }
                    List[j + d] = tmp;
                }

                d = d / 2;
            }

            return;
        }

        static void Main(string[] args)
        {
            int[] intArr = {10, 2, 56, 12, 6, 78, 34, 23, 9, 18, 7};

            ShellSort(intArr);

            for (int k = 0; k < intArr.Length; k++)
            Console.WriteLine(intArr[k]);
            Console.ReadKey();
        }
    }
}

3、冒泡排序(交换排序)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        public static void BubbleSort(int[] List)
        {
            int i = 0;
            int j = 0;
            int len = List.Length;
            int swap = 0;

            /*
            第一趟排序:通过两两比较,找到第一小的数值 1 ,将其放在序列的第一位。
            第二趟排序:通过两两比较,找到第二小的数值 2 ,将其放在序列的第二位。
            第三趟排序:通过两两比较,找到第三小的数值 3 ,将其放在序列的第三位。
            至此,所有元素已经有序,排序结束。
            */
            for (i = len - 1; i >= 0; i--)
            {
                for (j = len - 1; j >= len - i; j--)
                {
                    if (List[j] < List[j - 1])
                    {
                        swap = List[j];
                        List[j] = List[j - 1];
                        List[j - 1] = swap;
                    }
                }
            }

            return;
        }

        static void Main(string[] args)
        {
            int[] intArr = {10, 2, 56, 12, 6, 78, 34, 23, 9, 18, 7};

            BubbleSort(intArr);

            for (int k = 0; k < intArr.Length; k++)
            Console.WriteLine(intArr[k]);
            Console.ReadKey();
        }
    }
}

4、 快速排序(交换排序)

步骤:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        public static void QuickSort(int[] List, int left, int right)
        {
            int baseNum = 0;
            int low = 0;
            int high = 0;

            if (left < right)
            {
                baseNum = List[left];
                low = left;
                high = right;

                while (low < high)
                {
                    /* 从右往左扫描 */
                    while ((high > low) && (baseNum < List[high]))
                    {
                        high--;
                    }
                    List[low] = List[high];

                    /* 从左往右扫描 */
                    while ((low < high) && (baseNum > List[high]))
                    {
                        low++;
                    }
                    List[high] = List[low];
                }

                List[low] = baseNum;
                QuickSort(List, left, low - 1);
                QuickSort(List, low + 1, right);
            }

            return;
        }

        static void Main(string[] args)
        {
            int[] intArr = {10, 2, 56, 12, 6, 78, 34, 23, 9, 18, 7};

            QuickSort(intArr, 0, intArr.Length - 1);

            for (int k = 0; k < intArr.Length; k++)
            Console.WriteLine(intArr[k]);
            Console.ReadKey();
        }
    }
}

5、简单选择排序(直接选择排序):

(1) 从待排序序列中,找到关键字最小的元素;

(2) 如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;

(3) 从余下的 N - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        public static void SelectionSort(int[] List)
        {
            int index = 0;
            int swap = 0;
            int len = List.Length;
            int i = 0;
            int j = 0;

            for (; i < len; i++)
            {
                /* 找到这一趟循环最小的值,记录下标,默认下标为i */
                index = i;
                for (j = i + 1; j < len; j++)
                {
                    if (List[j] < List[index])
                    {
                        index = j;
                    }
                }

                /* 如果下标有改变,就交换数值 */
                if (index != i)
                {
                    swap = List[i];
                    List[i] = List[index];
                    List[index] = swap;
                }
            }

            return;
        }

        static void Main(string[] args)
        {
            int[] intArr = {10, 2, 56, 12, 6, 78, 34, 23, 9, 18, 7};

            SelectionSort(intArr);

            for (int k = 0; k < intArr.Length; k++)
            Console.WriteLine(intArr[k]);
            Console.ReadKey();
        }
    }
}

6、 堆排序

步骤:

(1)根据初始数组去构造初始堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大)。

(2)每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        public static void HeapAdjust(int[] array, int parent, int length)
        {

            int temp = array[parent]; // temp保存当前父节点
            int child = 2 * parent + 1; // 先获得左孩子

            while (child < length)
            {
                // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点

                if (child + 1 < length && array[child] < array[child + 1])
                {
                    child++;
                }

                // 如果父结点的值已经大于孩子结点的值,则直接结束

                if (temp >= array[child])
                {
                    break;
                }

                // 把孩子结点的值赋给父结点
                array[parent] = array[child];

                // 选取孩子结点的左孩子结点,继续向下筛选
                parent = child;
                child = 2 * child + 1;
            }

            array[parent] = temp;
        }

        public static void HeapSort(int[] list)
        {
            // 循环建立初始堆
            for (int i = list.Length / 2; i >= 0; i--)
            {
                HeapAdjust(list, i, list.Length - 1);

            }

            // 进行n-1次循环,完成排序
            for (int i = list.Length - 1; i > 0; i--)
            {
                // 最后一个元素和第一元素进行交换
                int temp = list[i];
                list[i] = list[0];
                list[0] = temp;

                // 筛选 R[0] 结点,得到i-1个结点的堆
                HeapAdjust(list, 0, i);
            }

        }

        static void Main(string[] args)
        {
            int[] intArr = {10, 2, 56, 12, 6, 78, 34, 23, 9, 18, 7};

            HeapSort(intArr);

            for (int k = 0; k < intArr.Length; k++)
            Console.WriteLine(intArr[k]);
            Console.ReadKey();
        }
    }
}

7、 归并排序

步骤:

(1)“分解”——将序列每次折半划分。

(2)“合并”——将划分后的序列段两两合并后排序。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        public static void Merge(int[] array, int low, int mid, int high)
        {
            int i = low; // i是第一段序列的下标
            int j = mid + 1; // j是第二段序列的下标
            int k = 0; // k是临时存放合并序列的下标
            int[] array2 = new int[high - low + 1]; // array2是临时合并序列

            // 扫描第一段和第二段序列,直到有一个扫描结束
            while (i <= mid && j <= high)
            {
                // 判断第一段和第二段取出的数哪个更小,将其存入合并序列,并继续向下扫描
                if (array[i] <= array[j])
                {
                    array2[k] = array[i];
                    i++;
                    k++;
                }
                else
                {
                    array2[k] = array[j];
                    j++;
                    k++;
                }
            }

            // 若第一段序列还没扫描完,将其全部复制到合并序列
            while (i <= mid)
            {
                array2[k] = array[i];
                i++;
                k++;
            }

            // 若第二段序列还没扫描完,将其全部复制到合并序列
            while (j <= high)
            {
                array2[k] = array[j];
                j++;
                k++;
            }

            // 将合并序列复制到原始序列中
            for (k = 0, i = low; i <= high; i++, k++)
            {
                array[i] = array2[k];
            }
        }

        public static void MergePass(int[] array, int gap, int length)
        {
            int i = 0;

            // 归并gap长度的两个相邻子表
            for (i = 0; i + 2 * gap - 1 < length; i = i + 2 * gap)
            {
                Merge(array, i, i + gap - 1, i + 2 * gap - 1);
            }

            // 余下两个子表,后者长度小于gap
            if (i + gap - 1 < length)
            {
                Merge(array, i, i + gap - 1, length - 1);
            }
        }

        public static int[] MergeSort(int[] list)
        {
            for (int gap = 1; gap < list.Length; gap = 2 * gap)
            {
                MergePass(list, gap, list.Length);
            }
            return list;
        }

        static void Main(string[] args)
        {
            int[] intArr = {10, 2, 56, 12, 6, 78, 34, 23, 9, 18, 7};

            MergeSort(intArr);

            for (int k = 0; k < intArr.Length; k++)
            Console.WriteLine(intArr[k]);
            Console.ReadKey();
        }
    }
}
时间: 2024-10-01 07:48:41

七种常用排序算法的相关文章

七种经典排序算法最全攻略

经典排序算法在面试中占有很大的比重,也是基础.包括冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序.希望能帮助到有需要的同学.全部程序采用JAVA实现. 本篇博客所有排序实现均默认从小到大. 一.冒泡排序 BubbleSort 介绍: 冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来. 步骤: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对第0个到第n-1个数据做同样的工作.这时,最大的数就"浮"到了

几种常用排序算法温习

几种常用排序算法温习 一. 简单排序方法 1.直接插入排序 基本思想:顺序地将待排序的记录按其关键码的大小插入到已排序的记录子序列的适当位置. 算法代码: //直接插入排序 public static void InsertSort(SeqList<int> seq) { if (seq.IsEmpty() || seq.GetLength() == 1) return; Console.Write("1.1 简单排序 排序前:"); seq.Display(); int

几种常用排序算法的python实现

1:快速排序 思想: 任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序. 一趟快速排序的算法是: 1)设置两个变量i.j,排序开始的时候:i=0,j=N-1: 2)以第一个数组元素作为关键数据,赋值给key,即key=A[0]: 3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]赋给A[i]: 4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大

视觉直观感受7种常用排序算法

视觉直观感受若干常用排序算法 1 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 "基准"(pivo

几种常用排序算法 (一)

八大常用排序算法详细分析 包括复杂度: 排序有可以分为以下几类: (1).交换排序:冒泡排序.快速排序 (2).选择排序:直接选择排序.堆排序 (3).插入排序:直接插入排序.希尔排序 (4).归并排序 (5).基数排序(桶排序) 1.冒泡排序 顾名思义,冒泡排序就是用气泡从下往上冒的原理,将气泡(较小或较大的数)依次往前移. 具体做法(升序):设总共有N个元素,则至少需要进行N-1次冒泡.一次排序排序中,若前一个元素大于后一个元素,则交换两个元素,然后在依次判  断后面两两相邻元素大小并进行交

数据结构——排序——8种常用排序算法稳定性分析

首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同.在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前. 其次,说一下稳定性的好处.排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用.基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的.另外,如果排序算法稳定,对基于比较的排序算法而言

几种常用排序算法(bubble、select、insert、shell、未完待续)

接下来两天重新看看几种常用的排序算法. 1.冒泡排序法 每次从 i=0开始比较相邻的元素,若arr[i]>arr[i+1],则交换它们.直到把最大的元素推向最后.回到 i=0,直至完成. 1 import java.util.Scanner; 2 class bubble 3 { 4 public static void main(String[] args) 5 { 6 int n,temp; 7 int i,j; 8 int[] arr=new int[10000]; 9 Scanner s

【轻松学排序算法】眼睛直观感受几种常用排序算法(转)

1 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 "基准"(pivot), 重新排序数列,所有元素

4.1_8种常用排序算法(上)

[8中排序算法一览] [算法1:冒泡排序] [冒泡算法实例] package com.sort.demo1; import java.util.Arrays; /** * 冒泡排序 */ public class BubbleSort { public static void main(String[] args) { int[] arr = new int[]{1,4,5,7,3,9,8,0,2,6}; System.out.println(Arrays.toString(arr)); bub