如下所示采用数组的最佳算法是什么:
A {0,1,2,3}
我希望订购它如下面的数组:
B {3,1,0,2}
有什么想法吗?
答案 0 :(得分:6)
因此,如果你有两个数组并且它们以不同的顺序保存相同的数据,那么就这样做:
A = B
我怀疑这不是你的情况所以我认为我们需要更多的信息。
答案 1 :(得分:3)
您需要做的是确定B的顺序,然后将该顺序应用于A.实现此目的的一种方法是撤消B的排序并跟踪沿途发生的情况。然后你可以反过来做A。
这是一些粗略的C#(对不起,我实际上并没有这样做)......
拿一份B:
List<int> B2 = new List<int>(B);
现在使用记录掉期的排序函数对其进行排序:
List<KeyValuePair<int,int>> swaps = new List<KeyValuePair<int,int>>();
B2.Sort( delegate( int x, int y ) {
if( x<y ) return -1;
if( x==y ) return 0;
// x and y must be transposed, so assume they will be:
swaps.Add( new KeyValuePair<int,int>(x,y) );
return 1;
});
现在以相反的顺序将交换应用于A:
swaps.Reverse();
foreach( KeyValuePair<int,int> x in swaps )
{
int t = A[x.key];
A[x.key] = A[x.value];
A[x.value] = t;
}
根据内置排序算法的工作原理,您可能需要自己滚动。像合并排序这样的非破坏性的东西可以给你正确的结果。
答案 2 :(得分:2)
这是我对比较器的实现(使用LINQ,但可以很容易地适应旧的.net版本)。您可以将它用于任何排序算法,例如Array.Sort,Enumerable.OrderBy,List.Sort等。
var data = new[] { 1, 2, 3, 4, 5 };
var customOrder = new[] { 2, 1 };
Array.Sort(data, new CustomOrderComparer<int>(customOrder));
foreach (var v in data)
Console.Write("{0},", v);
结果为2,1,3,4,5,
- customOrder中未列出的任何项目都放在给定类型的默认值的末尾(除非给出了回退比较器)
public class CustomOrderComparer<TValue> : IComparer<TValue>
{
private readonly IComparer<TValue> _fallbackComparer;
private const int UseDictionaryWhenBigger = 64; // todo - adjust
private readonly IList<TValue> _customOrder;
private readonly Dictionary<TValue, uint> _customOrderDict;
public CustomOrderComparer(IList<TValue> customOrder, IComparer<TValue> fallbackComparer = null)
{
if (customOrder == null) throw new ArgumentNullException("customOrder");
_fallbackComparer = fallbackComparer ?? Comparer<TValue>.Default;
if (UseDictionaryWhenBigger < customOrder.Count)
{
_customOrderDict = new Dictionary<TValue, uint>(customOrder.Count);
for (int i = 0; i < customOrder.Count; i++)
_customOrderDict.Add(customOrder[i], (uint) i);
}
else
_customOrder = customOrder;
}
#region IComparer<TValue> Members
public int Compare(TValue x, TValue y)
{
uint indX, indY;
if (_customOrderDict != null)
{
if (!_customOrderDict.TryGetValue(x, out indX)) indX = uint.MaxValue;
if (!_customOrderDict.TryGetValue(y, out indY)) indY = uint.MaxValue;
}
else
{
// (uint)-1 == uint.MaxValue
indX = (uint) _customOrder.IndexOf(x);
indY = (uint) _customOrder.IndexOf(y);
}
if (indX == uint.MaxValue && indY == uint.MaxValue)
return _fallbackComparer.Compare(x, y);
return indX.CompareTo(indY);
}
#endregion
}
答案 3 :(得分:1)
在您给出的示例(数组数组)中,重新排序A没有意义,因为您可以使用B。
因此,可能这些是您想要由其中一个属性排序的对象数组。
然后,您需要一种基于相关属性(如哈希表)在A中查找项目的方法。然后你可以迭代B(它是所需的序列),并对A中的相应元素进行操作。
答案 4 :(得分:1)
两个数组都包含相同的值(或几乎相同),但我需要强制它们处于相同的顺序。例如,在数组A中,值“3045”在索引位置4,在数组B中,它在索引位置1.我想重新排序B,以便类似值的索引位置与A相同。
答案 5 :(得分:1)
如果它们几乎相同,那么这里有一些伪代码:
Make an ArrayList
Copy the contents of the smaller array to the arraylist
for each item I in the larger array
FInd I in the ArrayList
Append I to a new array
Remove I from the arraylist
答案 6 :(得分:1)
是否可以使用字典解决问题,以便元素的关系完全不依赖于排序顺序?