【发布时间】:2025-12-03 07:35:02
【问题描述】:
我正在制作一个 meme 排名应用程序,它可以将您最喜欢的 meme 排名从最好到最差,并删除排名最低的 meme,以消除旧的和过时的 meme 中的额外膨胀,从而节省磁盘空间。我认为因为List<T>.Sort() 功能非常快,它会很快帮助用户对可能数百个模因进行分类。情况并非如此,因为当我尝试使用下面的方法进行排序时,我得到了一些奇怪的结果。
// Using Task.Run() temp. due to the easy access. Will thread this properly in the future.
Task.Run(() =>
{
Manager.Files.Sort(delegate (Photo x, Photo y) {
// I have Invoke built into the ChangeImage method but having double duty doesn't slow it down.
Invoke(new MethodInvoker(() =>
{
ChangeImage(pictureBox1, x.Filename);
ChangeImage(pictureBox2, y.Filename);
}));
WaitForButtonPress.WaitOne(); // Pauses the thread until an image is chosen.
switch (LastButton)
{
case 1: // if x is better than y
return 1;
case 2: // if y is better than x
return -1;
case 3: // if y and x are equals
return 0;
default:
break;
}
return 0;
});
});
我在这段代码中遇到的问题是,有时pepe.jpg 和isThisAPidgon.png 经常被相互比较多次,尤其是在连续出现比较后。 pepe.jpg vs.1.jpg,pepe.jpg vs.2.png...pepe.jpeg vs.nth.jpg,pepe.jpg vs.isThisAPidgon.png,然后又是isThisAPidgon.png vs.pepe.jpg .在发现这种奇怪的行为后,我尝试检查它们被调用了多少次。
static void Main(string[] args)
{
List<Number> numbers = new List<Number>();
Random rand = new Random();
for (int i = 0; i < 500; i++)
{
numbers.Add(new Number() { Num = rand.Next(0, 500) });
}
foreach(Number num in numbers)
{
Console.WriteLine(num.num);
}
numbers.Sort((Number x, Number y) =>
{
int numx = x.Num;
int numy = y.Num;
if (numx > numy)
return 1;
else if (numy > numx)
return -1;
else
return 0;
//return x.Num - y.Num;
});
int total = 0;
foreach(Number num in numbers)
{
Console.WriteLine($"Num: {num.num} Times Checked: {num.timesChecked}");
total += num.timesChecked;
}
Console.WriteLine($"Finished with {total} checks.");
}
班级编号:
class Number
{
public Number()
{
}
public int num;
public int timesChecked = 0;
public int Num { get { timesChecked++; return num; } set => num = value; }
}
< == > 比较返回 1、-1 或 0 并返回 x.num 和 y.num 的差异,两者产生相同的结果:有些出现的频率比有些高。以下是一些示例。
#checked with differences
Num: 168 Times Checked: 8
Num: 170 Times Checked: 17
Num: 170 Times Checked: 316 #316?
Num: 170 Times Checked: 14
Num: 171 Times Checked: 15
#checked with differences
Num: 237 Times Checked: 12
Num: 237 Times Checked: 9
Num: 240 Times Checked: 105 #More reasonable...
Num: 241 Times Checked: 14
Num: 242 Times Checked: 15
#checked with differences
Num: 395 Times Checked: 10
Num: 397 Times Checked: 8
Num: 398 Times Checked: 502 #How could it fail to sort this number in more tries than the array is long?
Num: 398 Times Checked: 7
Num: 399 Times Checked: 8
#checked with <==>
Num: 306 Times Checked: 15
Num: 306 Times Checked: 17
Num: 307 Times Checked: 756 #This is ridiculous how does this happen?
Num: 307 Times Checked: 13
Num: 309 Times Checked: 15
似乎差异总检查数低于 10000,但使用 /1,-1,0 方法检查时,总检查数似乎始终高于 15000。有没有一种排序算法专注于减少需要比较对象才能进行排序的次数?
编辑:我在 比较示例中犯了一个错误。我使用x.Num 和y.Num 两次,结果夸大了。为了解决这个问题,我将这两个属性存储为本地变量,它在 9000 左右将总数从 15000 以上下降到 10000 以下,同时在 8000 左右减去 sill 仍然低于 10000。
【问题讨论】:
-
你的比较是传递性的吗?这意味着如果
A<B那么另外,B>A必须是真的?如果A<=B和B<=C那么它给出了A<=C也必须是真的? -
@LasseV.Karlsen 是的,这是真的。只要
A<B的真实性没有改变,那么每个内存中出现的顺序无关紧要,所以这肯定意味着A<=B,B<=C因此A<=C。