c#: List.Sort()实现稳固排序(stable sort)
1. 源起:
KV 7.0加入列表管理功能,处理排序问题时,对空列表执行按大小、日期、长度排序发现,其中次序会发生改变,令人纳闷。
没天理呀,不应该啊!List.Sort()方法,它为什么?
对此问题深入去了解,倒发现了有趣的问题:稳固排序与非稳固排序。
2、稳固排序与非稳固排序
在微软官方网站找到此段说明:
Remarks
If comparison is provided, the elements of the List<T> are sorted using the method represented by the delegate.
If comparison is null, an ArgumentNullException is thrown.
This method uses Array.Sort, which applies the introspective sort as follows:
If the partition size is fewer than 16 elements, it uses an insertion sort algorithm
If the number of partitions exceeds 2 * LogN, where N is the range of the input array, it uses a Heapsort algorithm.
Otherwise, it uses a Quicksort algorithm.
This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved. In contrast, a stable sort preserves the order of elements that are equal.
On average, this method is an O(n log n) operation, where n is Count; in the worst case it is an O(n ^ 2) operation.
大意是此实现将执行不稳定排序。也就是说,如果两个元素相等,则可能不会保留其顺序。
我们建Demo做验证,用例如下:
var list = new List<string>();
list.AddRange(new string[] { "", "", "", "" }); list.Sort((x, y) =>
{
return ;
}); foreach (string s in list)
Console.WriteLine(s);
其输出为:

验证上述结果,推测它是使用了二分法快速反序,把后半部分置前了。
可八辈的我们宁愿它输入为原始顺序3214,这个合理,但是,可是,它无耻的变了……
3、实际场景
比如,我们需要对特定的对象进行排序,如下摘取网上例子(链接)稍加修正,以做示例:
static void Main(string[] args)
{
var p1 = new Person() { Name = "Abby", Age = };
var p4 = new Person() { Name = "Jason", Age = };
var p2 = new Person() { Name = "Bob", Age = };
var p3 = new Person() { Name = "Charlie", Age = };
var p5 = new Person() { Name = "Danielle", Age = }; var list = new List<Person>();
list.Add(p1);
list.Add(p2);
list.Add(p3);
list.Add(p4);
list.Add(p5);
list.Sort(); Console.WriteLine("Unstable List Sort:");
foreach (Person p in list)
Console.WriteLine(p); Console.ReadLine();
} class Person : IComparable
{
public string Name { get; set; }
public int Age { get; set; } public int CompareTo(object obj)
{
int result = ;
if (obj != null && obj is Person)
{
var person = (Person)obj;
result = this.Age.CompareTo(person.Age);;
}
return result;
} public override string ToString()
{
return String.Format("{0} - {1}", this.Name, this.Age);
}
}
其输出为:

其中间23岁之三项,没有按Jason、Bob、Charlie的次序来,甚至也不是倒序。
我就是想要它加入顺序不变,怎么办?
对此问题,搜出一些文章,有建议用LINQ排序因为它是稳固排序,可我们工程所用.net framework版本为2.0,不支持,只好做罢。
在stackoverflow上,碰到一群难兄难弟,诸般建议阅过,找到可用方法,加索引!
4、解决方法
且修改Person类,加入SortIndex属性如下,并修正其比较函数:
class Person : IComparable
{
public string Name { get; set; }
public int Age { get; set; }
public int SortIndex { get; set; }
public int CompareTo(object obj)
{
int result = ;
if (obj != null && obj is Person)
{
var person = (Person)obj;
result = this.Age.CompareTo(person.Age); if (result == )
result = this.SortIndex.CompareTo(person.SortIndex);
}
return result;
}
...
}
初始化时,加入其索引:
var p1 = new Person() { Name = "Abby", Age = , SortIndex = };
var p4 = new Person() { Name = "Jason", Age = , SortIndex = };
var p2 = new Person() { Name = "Bob", Age = , SortIndex = };
var p3 = new Person() { Name = "Charlie", Age = , SortIndex = };
var p5 = new Person() { Name = "Danielle", Age = , SortIndex = };
输出顺序:

保留初始顺序,解决问题。
后记:
之前未曾留意,此问题发现倒是很有意思,度娘不给力,解决问题还是要google,在stackoverflow上找到有同困扰之人,得其可参考方案。
此场景,通常用于自定义数据结构比较,如KV项目之空白列表,当其可比较项相等时,应该保留其原始顺序,可是被改变了,导致寻求解决问题的方法。
但在官方方案已固定不能改变之情况下,做个曲线救国,加另一索引以固定次序,虽然看来费些点工夫,但是能解决问题,不失为好的可用方法。
参考文档:
List(T).Sort Method (Comparison(T)) (System.Collections.Generic)
Why does List<T>.Sort method reorder equal IComparable<T> elements?
c#: List.Sort()实现稳固排序(stable sort)的更多相关文章
- C#中List调用库函数sort进行升序排序
private void button1_Click(object sender, EventArgs e) { List<int> demo2 = new List<int> ...
- python 排序之sort
#coding:utf-8 #求列表的第二大值 list_test =[6,2,4,6,1,2,3,4,5] list_test.sort() print list_test[-2] "&q ...
- 计数排序与桶排序(bucket sort)
Bucket Sort is a sorting method that subdivides the given data into various buckets depending on cer ...
- 数据结构杂谈(二)简单有趣的地精排序Gnome sort
很早之前便听说过地精排序的名字,今天自己看来一下,发现这是一种非常简单而且有趣的排序算法. 为什么叫地精排序? 地精排序在2000年由Dr. Hamid Sarbazi-Azad 提出的时候被称作 s ...
- sort 树 hash 排序
STL 中 sort 函数用法简介 做 ACM 题的时候,排序是一种经常要用到的操作.如果每次都自己写个冒泡之类的 O(n^2) 排序,不但程序容易超时,而且浪费宝贵的比赛时间,还很有可能写错. ST ...
- python 字典排序 关于sort()、reversed()、sorted()
一.Python的排序 1.reversed() 这个很好理解,reversed英文意思就是:adj. 颠倒的:相反的:(判决等)撤销的 print list(reversed(['dream','a ...
- (C++)STL排序函数sort和qsort的用法与区别
主要内容: 1.qsort的用法 2.sort的用法 3.qsort和sort的区别 qsort的用法: 原 型: void qsort(void *base, int nelem, int widt ...
- 排序命令sort
Unix和Linux自带的sort命令功能非常强大,其主要功能是对文本内容按不同的方法排序.它不仅可以按一个或多个字段排序,还可以合并文件.使用sort处理一些较大的文件时,可能处理速度会比较慢,但却 ...
- C++排序函数sort/qsort使用
问题描述: C++排序函数sort/qsort的使用 问题解决: (1)sort函数使用 注: sort函数,参数1为数组首地址,参数2是数组 ...
随机推荐
- Notepadd ++ PluginManager安装
下载地址https://github.com/bruderstein/nppPluginManager/releases 解压后有2个包plugins和updater 分别放入C:\Program F ...
- 使用linux的shell脚本实现在当前行重复动态显示时间等字符串信息(不另起新行)
###本脚本在Suse11sp2当中验证正确 #!/bin/sh )) do echo -ne "\r$(date)" sleep 0.3 done ###关键在 echo 的 & ...
- oracle 修改字符集 为ZHS16GBK
一.oracle server 端 字符集查询 select userenv('language') from dual 其中NLS_CHARACTERSET 为server端字符集 NLS_LANG ...
- ssm框架之配置日志系统打印到控制台与指定文件
前提: 0:ssm框架已经搭建并且成功运行 1.maven环境配置成功 2.tomcat配置成功,并且配置本机的tomcat环境变量 内容: 0.导入所需要的jar包 <!-- 配置log4j日 ...
- Xcode 新建bundle id不同的且app图标也不同的新的target的步骤
方法一: duplicate一个target 修改target配置文件中的bundle id,app icon图标文件位置(必要时重命名app icon文件名),plist文件位置,entitleme ...
- js中实现cookie的增删改查(document.cookie的使用详情)
一.设置cookie的值 1.每个cookie都是一个名称/值对,名称/值对用等号连接,并将该名称/值对赋值给document.cookie即可.如:document.cookie="id= ...
- IIS Express
当前程序员只能通过下面两种web服务器之一来开发和测试ASP.NET网站程序: 1. Visual Studio自带的ASP.NET开发服务器(webdev.exe). 2. Windows自带的II ...
- vscode项目配置 vue-loader-webpack
使用vsCode进行项目配置 一.准备工作 1.下载Visual Studio Code 下载地址 2.打开vscode,根据自己需求下载相应插件,可以提高工作效率. 点击下角选项(我作了红框标记), ...
- list 转datatable
//public static DataTable ListToDataTable(List<FwImage> entitys) //{ // //检查实体集合不能为空 // if (en ...
- Android中使用Lambda表达式开发
参考文章:ImportNew 要在Android开发中使用lambda表达式,首先需要在 Module 的build.gradle中加入: compileOptions { targetCompati ...