回复本论坛提问:譬如:一个一维数组a[100],如何快速的找到 最大的10个数和最小的五个数,输出这个15个数的数组下标?
周末把已有C++程序稍加修改为C#,足以证明算法跨语言:自然将收录在专栏内,以便查看.
/*从一维数组100个数据中选出最大10个数的下标及最小6个数的下标*/
int[] 数据 = { 3, 33, 333, 6, 66, 666, 9, 99, 999, 8, 88, 888, 5, 55, 555, 2, 22, 222, 1, 11, 111, 4, 44, 444, 7, 77, 777 },
大数 = Enumerable.Repeat(int.MinValue, 10).ToArray(), 小数 = Enumerable.Repeat(int.MaxValue, 6).ToArray(), 大下标 = new int[大数.Count()], 小下标 = new int[小数.Count()];
int 下标 = 0;
do
{
int 序 = 0, 排序大 = 大数.Count() - 1, 排序小 = 小数.Count() - 1;
do
{
if (数据[下标] > 大数[序])
{
while (排序大 - 序 > 0)
{
大下标[排序大] = 大下标[排序大 - 1];
大数[排序大] = 大数[排序大-- - 1];
}
大下标[序] = 下标;
大数[序] = 数据[下标];
}
if (序 <= 排序小)
if (数据[下标] < 小数[序])
{
while (排序小 - 序 > 0)
{
小下标[排序小] = 小下标[排序小 - 1];
小数[排序小] = 小数[排序小-- - 1];
}
小下标[序] = 下标;
小数[序] = 数据[下标];
}
} while (序++ < 排序大);
} while (++下标 < 数据.Count());
优化代码:
int[] 数据 = { 3, 33, 333, 6, 66, 666, 9, 99, 999, 8, 88, 888, 5, 55, 555, 2, 22, 222, 1, 11, 111, 4, 44, 444, 7, 77, 3333, 6666, 9999, 8888, 5555, 2222, 1111, 4444, 7777, 33333, 66666, 99999, 88888, 55555, 22222, 11111, 44444, 77777, 333333, 666666, 999999, 888888, 555555, 222222, 111111, 444444, 777777, 999999 },
大数 = Enumerable.Repeat(int.MinValue, 10).ToArray(), 小数 = Enumerable.Repeat(int.MaxValue, 6).ToArray(), 大下标 = new int[大数.Count()], 小下标 = new int[小数.Count()];
int 下标 = 0, 序 = 0, 排序大 = 大数.Count() - 1, 排序小 = 小数.Count() - 1;
do
{
if (序 < 排序大)
{
if (数据[下标] > 大数[序])
{
while (排序大 - 序 > 0)
{
大下标[排序大] = 大下标[排序大 - 1];
大数[排序大] = 大数[排序大-- - 1];
}
大下标[序] = 下标;
大数[序] = 数据[下标];
}
if (序 <= 排序小)
if (数据[下标] < 小数[序])
{
while (排序小 - 序 > 0)
{
小下标[排序小] = 小下标[排序小 - 1];
小数[排序小] = 小数[排序小-- - 1];
}
小下标[序] = 下标;
小数[序] = 数据[下标];
}
++序;
}
else
{
序 = 0;
排序大 = 大数.Count() - 1;
排序小 = 小数.Count() - 1;
++下标;
}
} while (下标 < 数据.Count());
以上从已经发布的参考代码1 以及参考代码2 演变而来,之下将发布再次优化的代码,见证程序从最简最易开始不断的演变经历。
int[] 数据 = { 3, 33, 333, 6, 66, 666, 9, 99, 999, 8, 88, 888, 5, 55, 555, 2, 22, 222, 1, 11, 111, 4, 44, 444, 7, 77, 3333, 6666, 9999, 8888, 5555, 2222, 1111, 4444, 7777, 33333, 66666, 99999, 88888, 55555, 22222, 11111, 44444, 77777, 333333, 666666, 999999, 888888, 555555, 222222, 111111, 444444, 777777, 999999 },
大数 = Enumerable.Repeat(int.MinValue, 10).ToArray(), 小数 = Enumerable.Repeat(int.MaxValue, 6).ToArray(), 大下标 = new int[大数.Count()], 小下标 = new int[小数.Count()];
int 下标 = 0, 序 = 0, 排序大 = 大数.Count() - 1, 排序小 = 小数.Count() - 1;
Action<int, int[], int[]> 有参无返值 = delegate(int 排序, int[] 序组, int[] 数组)
{
while (排序 - 序 > 0)
{
序组[排序] = 序组[排序 - 1];
数组[排序] = 数组[排序-- - 1];
}
序组[序] = 下标;
数组[序] = 数据[下标];
排序大 = 0;
排序小 = 0;
};
do
{
if (序 < 排序大)
{
if (数据[下标] > 大数[序])
有参无返值(排序大, 大下标, 大数);
if (序 <= 排序小)
if (数据[下标] < 小数[序])
有参无返值(排序小, 小下标, 小数);
++序;
}
else
{
序 = 0;
排序大 = 大数.Count() - 1;
排序小 = 小数.Count() - 1;
++下标;
}
} while (下标 < 数据.Count());