C#实现8种基础排序算法

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

namespace SortFunc
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> list = (new int[10] { -23, -77, 6, 123, 43, 76, 84, 213, 78, -56 }).ToList();
            //Sort.SelectSort(list);
            //Sort.BubbleSort(list);
            //Sort.InsertSort(list);
            //Sort.QuickSort(list);
            //list = Sort.MergeSort(list);
            //Sort.HeapSort(list);
            //Sort.ShellSort(list);
            list = Sort.RadixSort(list);
            for (int i = 0; i < list.Count; i++)
            {
                Console.WriteLine(list[i]);
            }
            Console.ReadKey();
        }
    }
    class Sort
    {
        /// <summary>
        /// 选择排序
        /// 原理:找出数组最大值放在末尾或者最小值放在排头
        /// </summary>
        /// <param name="list"></param>
        public static void SelectSort(List<int> list)
        {
            for (int i = 0; i < list.Count-1; i++)
            {
                int minIndex = i;
                int temp = list[i];
                for (int j = i+1; j < list.Count; j++)
                {
                    if (temp > list[j])
                    {
                        minIndex = j;
                        temp = list[j];
                    }
                }
                if (minIndex != i)
                    Swap(list, i, minIndex);
            }
        }
        /// <summary>
        /// 冒泡排序
        /// 原理:从头开始,每一个元素和它的下一个元素比较,如果它大,就将它与比较的元素交换,否则不动。
        /// 这意味着,大的元素总是在向后慢慢移动直到遇到比它更大的元素。所以每一轮交换完成都能将最大值
        /// 冒到最后。
        /// </summary>
        /// <param name="list"></param>
        public static void BubbleSort(List<int > list)
        {
            for (int i = list.Count-1; i >0; i--)
            {
                for (int j = 0; j <i; j++)
                {
                    if (list[j] > list[j + 1])
                        Swap(list, j, j + 1);
                }
            }
        }
        /// <summary>
        /// 改良版冒泡排序,也有点选择排序得影子
        /// </summary>
        /// <param name="nums"></param>
        private void Sort(List<int> nums)
        {
        	int temp;
	        for (int i = 0; i < nums.Count-1; i++)
	        {
    	        temp = nums[i];
        	    for (int j = i+1; j < nums.Count; j++)
            	{
                	if (temp > nums[j])
                	{
                    	nums[i] = nums[j];
	                    nums[j] = temp;
    	                temp = nums[i];
        	        }
            	}
	        }
    	}
        /// <summary>
        /// 插入排序
        /// 原理:通过构建有序数列,将未排序的数从后向前比较,找到合适位置并插入。
        /// </summary>
        /// <param name="list"></param>
        public static void InsertSort(List<int> list)
        {
            int temp;
            //int curIndex;
            for (int i = 1; i < list.Count; i++)
            {
                temp = list[i];
                //curIndex = i;
                for (int j = i - 1; j >= 0; j--)
                {
                    if (temp > list[j])//大于j就在j索引后面,退出当前排序
                    {
                        list[j + 1] = temp;
                        break;
                    }
                    else//反之就在前面,记住索引继续排序
                    {
                        //Swap(list, curIndex, j);
                        //curIndex = j;
                        list[j + 1] = list[j];
                        if(j==0)
                        {
                            list[0] = temp;
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 快速排序
        /// 原理:从数列中挑选一个数作为“哨兵”,使比它小的放在它的左侧,比它大的放在它的右侧。将要排序是数列递归地分割到
        /// 最小数列,每次都让分割出的数列符合“哨兵”的规则,自然就将数列变得有序。
        /// </summary>
        /// <param name="list"></param>
        public static void QuickSort(List<int> list)
        {
            QuickSort(list, 0, list.Count - 1);
        }
        private static void QuickSort(List<int> list,int left,int right)
        {
            if (left >= right)
                return;
            int temp = list[left];
            int i = left + 1, j = right;
            while (true)
            {
                while (list[j] > temp) j--;
                while (list[i] < temp && i < j) i++;
                if (i >= j)
                    break;
                Swap(list, i, j);
                i++;j--;
            }
            if (j != left)
                Swap(list, left, j);
            QuickSort(list, j + 1, right);
            QuickSort(list, left, j - 1);
        }
        private static void QuickSort2(List<int> list, int left, int right)
        {
            if (left >= right) return;
            int temp = list[(left + right) / 2];
            int i = left - 1, j = right + 1;
            while (true)
            {
                while (list[++i] < temp) ;
                while (list[--j] > temp) ;
                if (i >= j) break;
                Swap(list, i, j);
            }
            QuickSort2(list, left, i - 1);
            QuickSort2(list, j + 1, right);
        }
        /// <summary>
        /// 归并排序(合并排序)
        /// 原理:将两个有序的数列,通过比较,合并为一个有序数列。
        /// </summary>
        /// <param name="list"></param>
        public static List<int> MergeSort(List<int > list)
        {
            return MergeSort(list, 0, list.Count - 1);
            //return MergeSortOnlyList(list, 0, list.Count - 1);
        }
        private static List<int > MergeSort(List<int> list,int left,int right)
        {
            if (left == right)
                return new List<int> { list[left] };
            List<int> mergeData = new List<int>();
            int center = (left + right) / 2;
            List<int> leftList = MergeSort(list, left, center);
            List<int> rightList = MergeSort(list, center + 1, right);
            int i = 0, j = 0;
            while (true)
            {
                if(leftList[i]<rightList[j])
                {
                    mergeData.Add(leftList[i++]);
                    if(i==leftList.Count)
                    {
                        mergeData.AddRange(rightList.GetRange(j, rightList.Count - j));
                        break;
                    }
                }
                else
                {
                    mergeData.Add(rightList[j++]);
                    if(j==rightList.Count)
                    {
                        mergeData.AddRange(leftList.GetRange(i, leftList.Count - i));
                        break;
                    }
                }
            }
            return mergeData;
        }
        public static List<int> MergeSortOnlyList(List<int> data, int low, int high)
        {
            if (low == high)
                return new List<int> { data[low] };
            List<int> mergeData = new List<int>();
            int mid = (low + high) / 2;
            List<int> leftData = MergeSortOnlyList(data, low, mid);
            List<int> rightData = MergeSortOnlyList(data, mid + 1, high);
            int i = 0, j = 0;
            while (true)
            {
                if (leftData[i] < rightData[j])
                {
                    mergeData.Add(leftData[i]);
                    if (++i == leftData.Count)
                    {
                        mergeData.AddRange(rightData.GetRange(j, rightData.Count - j));
                        break;
                    }
                }
                else
                {
                    mergeData.Add(rightData[j]);
                    if (++j == rightData.Count)
                    {
                        mergeData.AddRange(leftData.GetRange(i, leftData.Count - i));
                        break;
                    }
                }
            }
            return mergeData;
        }
        /// <summary>
        /// 堆排序(都是从小到大)
        /// 原理:将数列构建为最大堆数列(即父节点总是最大值),将最大值(即根节点)交换到数列末尾。这样要排序的数列数总和减少,
        /// 同时根节点不再是最大值,调整最大堆数列。如此重复,最后得到有序数列
        /// </summary>
        /// <param name="list"></param>
        public static void HeapSort(List<int> list)
        {
            BuildMaxHeap(list);//第一轮排序完之后,父节点都大于子节点
            int j = list.Count;
            for (int i = 0; i < j; )
            {
                //将每轮的根节点的(剩余数中最大)放在最后从后往前排列
                Swap(list, i, --j);
                if (j - 2 < 0)//只剩下1个数 j代表余下要排列的数的个数
                    break;
                int k = 0;
                while(true)
                {
                    if (k > (j - 2) / 2)//超出最后一个父节点的位置
                        break;
                    else
                    {
                        int temp = k;
                        k = ReSortMaxBranch(list, k, 2 * k + 1, 2 * k + 2, j - 1);
                        if (temp == k)
                            break;
                    }
                }
            }
        }
        private static void BuildMaxHeap(List<int> list)
        {
            for (int i = list.Count / 2 - 1; i >= 0; i--)
            {
                int temp = i;
                temp = ReSortMaxBranch(list, i, 2 * i + 1, 2 * i + 2, list.Count - 1);
                if (temp != i)//返回索引不是父节点
                {
                    int k = i;
                    while (k != temp && temp <= list.Count / 2 - 1)//计算一次后如果父节点比子节点大&&如果没有子节点
                    {
                        k = temp;
                        temp = ReSortMaxBranch(list, temp, 2 * temp + 1, 2 * temp + 2, list.Count - 1);
                    }
                }
            }
        }
        private static int ReSortMaxBranch(List<int> list,int maxIndex,int left,int right,int lastIndex)
        {
            int temp;
            if (right > lastIndex)//说明父节点只有一个子节点
                temp = left;
            else
            {
                if (list[left] > list[right])//判断两个子节点哪个大
                    temp = left;
                else
                    temp = right;
            }

            if (list[maxIndex] < list[temp])//如果父节点比子节点小,交换索引,返回子节点索引
                Swap(list, maxIndex, temp);
            else
                temp = maxIndex;//否则返回父节点索引
            return temp;
        }
        /// <summary>
        /// 希尔排序
        /// 原理:通过奇妙的步长,插入排序间隔步长的元素,随后逐渐缩短步长至1,实现数列的插入排序。
        /// (不太理解他这怎么缩进的)
        /// </summary>
        /// <param name="list"></param>
        public static void ShellSort(List<int> list)
        {
            int temp;
            for (int gap = list.Count; gap > 0; gap /= 2)
            {
                for (int i = gap; i < list.Count; i += gap)//i+=gap改为i++
                {
                    temp = list[i];
                    for (int j = i - gap; j >= 0; j -= gap)
                    {
                        if (list[j] > temp)
                        {
                            list[j + gap] = list[j];
                            if (j == 0)
                            {
                                list[j] = temp;
                                break;
                            }
                        }
                        else
                        {
                            list[j + gap] = temp;
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 基数排序(暂时不理解,这个方法目前只支持正数)
        /// 原理:将整数按位数切割成不同的数字,然后按每个位数分别比较
        /// </summary>
        /// <param name="list"></param>
        public static List<int> RadixSort(List<int> list)
        {
            int max = list[0];
            for (int i = 1; i < list.Count; i++)
            {
                if (list[i] > max)
                    max = list[i];
            }
            int count = 1;//看多少位数
            while(max/10!=0)
            {
                count++;
                max /= 10;
            }
            for (int i = 0; i < count; i++)
            {
                int[] indexCounter = new int[10];
                List<int> tempList = new List<int>();
                tempList.AddRange(list);
                for (int j = 0; j < list.Count; j++)
                {
                    int number = (list[j] % Convert.ToInt32(Math.Pow(10, i + 1))) / Convert.ToInt32(Math.Pow(10, i));//得出i+1位上的数
                    indexCounter[number]++;
                }
                int[] indexBegin = new int[10];
                for (int k = 1; k < 10; k++)
                {
                    indexBegin[k] = indexBegin[k - 1] + indexCounter[k - 1];
                }
                for (int k = 0; k < list.Count; k++)
                {
                    int number = (list[k] % Convert.ToInt32(Math.Pow(10, i + 1))) / Convert.ToInt32(Math.Pow(10, i));
                    tempList[indexBegin[number]++] = list[k];
                }
                list = tempList;
            }
            return list;
        }
        #region 通用代码
        /// <summary>
        /// 交换位置
        /// </summary>
        /// <param name="list">集合</param>
        /// <param name="current">当前索引</param>
        /// <param name="swap">交换索引</param>
        public static void Swap(List<int> list,int current,int swap)
        {
            int temp = list[current];
            list[current] = list[swap];
            list[swap] = temp;
        }
        #endregion
    }
}

简介

排序算法是我们编程中遇到的最多的算法。目前主流的算法有8种。

平均时间复杂度从高到低依次是:

 冒泡排序(o(n2)),选择排序(o(n2)),插入排序(o(n2)),堆排序(o(nlogn)),

 归并排序(o(nlogn)),快速排序(o(nlogn)), 希尔排序(o(n1.25)),基数排序(o(n))

冒泡排序

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Alt

带尺寸的图片: Alt

居中的图片: Alt

居中并且带尺寸的图片: Alt

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目Value
电脑$1600
手机$12
导管$1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列第二列第三列
第一列文本居中第二列文本居右第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPEASCIIHTML
Single backticks'Isn't this fun?'‘Isn’t this fun?’
Quotes"Isn't this fun?"“Isn’t this fun?”
Dashes-- is en-dash, --- is em-dash– is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通过欧拉积分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

Mon 06 Mon 13 Mon 20 已完成 进行中 计划一 计划二 现有任务 Adding GANTT diagram functionality to mermaid
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

Created with Raphaël 2.2.0 开始 我的操作 确认? 结束 yes no
  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值