经典算法之七大排序

【交换排序】:冒泡排序,快速排序 【选择排序】:简单选择排序,堆排序

【插入排序】:简单插入排序,希尔排序 ;归并排序

一:交换排序

 public class BubbleSort
    {
        public static List<int> Sort(List<int> list)
        {
            int temp = 0;
            //要比较的次数 n-1
            for (int i = 0; i < list.Count - 1; i++)
            {   
                //从底部开始
                for (int j = list.Count - 1; j > i; j--)
                {   
                    //往下沉
                    if (list[j - 1]>list[j])
                    {
                        temp = list[j];
                        list[j] = list[j - 1];
                        list[j - 1] = temp;
                    }
                }
            }
            return list;
        }
    }

 快排

 1  public class QuickSort
 2     {
 3         public static void Sort(List<int> list,int left,int right)
 4         {
 5             if (left < right)
 6             {
 7                 int i = Division(list, left, right);
 8                 Sort(list, left, i - 1);
 9                 Sort(list,i+1,right);
10             }
11         }
12 
13         private static int Division(List<int> list, int left, int right)
14         {   
15             //挑选基准元素
16             int baseNum = list[left];
17 
18             while (left < right)
19             {   
20                 //从数组的右端开始向前找,一直找到比base小的数字为止
21                 while (left < right && list[right] >= baseNum)
22                 {
23                     right = right - 1;
24                 }
25                 list[left] = list[right];
26 
27                 while (left < right && list[left] <= baseNum)
28                 {
29                     left = left + 1;
30                 }
31                 list[right] = list[left];
32             }
33 
34             list[left] = baseNum;
35             
36             return left;
37         }

二:选择排序:

 1  public class SelectionSort
 2     {
 3         static void Sort(List<int> list)
 4         {
 5             for (int i = 0; i < list.Count - 1; i++)
 6             {   
 7                 //设置tempIndex的下标值
 8                 int tempIndex = i;
 9                 for (int j = i + 1; j < list.Count; j++)
10                 {
11                     if (list[tempIndex] > list[j])
12                     {
13                         tempIndex = j;
14                     }
15                 }
16 
17                 var tempData = list[tempIndex];
18                 list[tempIndex] = list[i];
19                 list[i] = tempData;
20             }
21         }
/// <summary>
    /// 堆排序(大根堆,小根堆)
    /// 大根堆(父结点比孩子结点都要大)
    /// 小跟堆(父结点比孩子结点都要小)
    /// </summary>
    public class HeapSort
    {
        public static void Sort(List<int> list)
        {   
            //list.Count/2-1:就是堆中父节点的个数
            for (int i = list.Count / 2 - 1; i >= 0; i--)
            {
                HeapAdjust(list, i, list.Count);
            }

            //最后输出堆
            for (int i = list.Count - 1; i > 0; i--)
            {   
                //堆顶与当前堆的第i个元素值对调,将对顶踢出,破换堆
                int temp = list[0];
                list[0] = list[i];
                list[i] = temp;

                //因为两值交换,可能破坏根堆,所以必须重新构造
                HeapAdjust(list, 0, i);
            }

        }

        private static void HeapAdjust(List<int> list, int parent, int length)
        {   
            //temp保留当前父结点
            int temp = list[parent];
            
            //得到左孩子(二叉树的定义)
            int child = 2 * parent + 1;

            while (child < length)
            {   
                //如果parent有右孩子,则判断左孩子是否小于右孩子
                if (child + 1 < length && list[child] < list[child + 1])
                    child++;

                if (temp > list[child])
                    break;

                //将较大结点的值赋给父结点
                list[parent] = list[child];

                //然后将子节点做为父亲节点,已防止是否破坏根堆时重新构造
                parent = child;

                //找到该父亲节点较小的左孩子节点
                child = 2 * parent + 1;
            }
            //最后将temp值赋给较大的子结点,形成两值交换
            list[parent] = temp;
        }

    
    }

三:插入排序

  /// <summary>
    /// 插入排序
    /// </summary>
    /// <remarks>
    /// 数组被划分为无序数组块和有序数组块
    /// </remarks>
    public class InsertSort
    {
        static void Sort(List<int> list)
        { 
            //无序序列
            for (int i = 1; i < list.Count; i++)
            {
                var temp = list[i];
                int j;

                //有序序列
                for (j = i - 1; j >= 0 && temp < list[j]; j--)
                {
                    list[j + 1] = list[j];
                }
                list[j + 1] = temp;

            }
        }
    }
 public class ShellSort
    {
        static void Sort(List<int> list)
        {   
            //取增量
            int step = list.Count/ 2;

            while (step >= 1)
            {
                for (int i = step; i < list.Count; i++)
                {
                    int temp = list[i];
                    int j;
                    for (j = i - step; j >= 0 && temp < list[j]; j = j - step)
                    {
                        list[j + step] = list[j];
                    }
                    list[j + step] = temp;
                }
                step = step / 2;
            }
        }
    }

四:归并排序

  /// <summary>
    /// 归并排序的过程
    /// 第一: “分”,  就是将数组尽可能的分,一直分到原子级别。
    ///第二: “并”,将原子级别的数两两合并排序,最后产生结果。
    /// </summary>
    public class MergeSort
    {
        static void Sort(int[] array, int[] temparray, int left, int right)
        {
            if (left < right)
            { 
                //取分割位置
                int middle = (left + right) / 2;

                //先递
                Sort(array, temparray, left, middle);

                Sort(array, temparray, middle + 1, right);

                //后归
                Merge(array, temparray, left, middle + 1, right);
            }
        }

        //数组的两两合并操作
        private static void Merge(int[] array, int[] temparray, int left, int middle, int right)
        {
            //左指针尾
            int leftEnd = middle - 1;
            //右指针头
            int rightStart = middle;

            //临时数组的下标
            int tempIndex = left;

            //数组合并后的length长度
            int tempLength = right - left + 1;

            //先循环两个区间都没有结束的情况
            while ((left <= leftEnd) && (rightStart <= right))
            {
                if (array[left] < array[rightStart])
                {
                    temparray[tempIndex++] = array[left++];
                }
                else
                {
                    temparray[tempIndex++] = array[rightStart++];
                }
            }

            //判断左序列是否结束
            while (left <= leftEnd)
                temparray[tempIndex++] = array[left++];

            while (rightStart <= right)
                temparray[tempIndex++] = array[rightStart++];

            //交换数据
            for (int i = 0; i < tempLength; i++)
            {
                array[right] = temparray[right];
                right--;
            }

        }
    }
发布了29 篇原创文章 · 获赞 1 · 访问量 8027

猜你喜欢

转载自blog.csdn.net/binfire/article/details/45827437