, , , , , . AddBefore(), , , , .
, , , , .
, , , Fisher-Yates, swap , ( Fisher-Yates).
, , , , , ( ).
, , . :
class Program
{
static void Main(string[] args)
{
LinkedList<int> test = new LinkedList<int>(Enumerable.Range(0, 10)),
shuffled = Shuffle(test);
Console.WriteLine(string.Join(", ", shuffled));
}
static LinkedList<T> Shuffle<T>(LinkedList<T> source)
{
LinkedList<T> result = new LinkedList<T>();
int[] choices = Enumerable.Range(0, source.Count).ToArray();
ShuffleArray(choices);
foreach (int choice in choices)
{
result.AddLast(ElementAt(source, choice));
}
return result;
}
static void ShuffleArray<T>(T[] array)
{
Random random = new Random();
for (int i = array.Length; i > 1; i--)
{
int j = random.Next(i);
if (i - 1 != j)
{
T t = array[i - 1];
array[i - 1] = array[j];
array[j] = t;
}
}
}
static T ElementAt<T>(LinkedList<T> source, int index)
{
LinkedListNode<T> current = source.First;
while (index-- > 0)
{
current = current.Next;
}
return current.Value;
}
}
/ , - :
class Program
{
static void Main(string[] args)
{
LinkedList<int> test = new LinkedList<int>(Enumerable.Range(0, 10));
ShuffleLinkedList(test);
Console.WriteLine(string.Join(", ", test));
}
static void ShuffleLinkedList<T>(LinkedList<T> list)
{
Random random = new Random();
for (int i = list.Count; i > 1; i--)
{
SwapNodes(list, i - 1, random.Next(i));
}
}
static void SwapNodes<T>(LinkedList<T> list, int i, int j)
{
if (i != j)
{
LinkedListNode<T> node1 = NodeAt(list, i), node2 = NodeAt(list, j),
nodeBefore1 = node1.Previous, nodeBefore2 = node2.Previous;
if (nodeBefore1 == node2)
{
list.Remove(node1);
AddAfter(list, nodeBefore2, node1);
}
else if (nodeBefore2 == node1)
{
list.Remove(node2);
AddAfter(list, nodeBefore1, node2);
}
else
{
list.Remove(node1);
list.Remove(node2);
AddAfter(list, nodeBefore2, node1);
AddAfter(list, nodeBefore1, node2);
}
}
}
static void AddAfter<T>(LinkedList<T> list, LinkedListNode<T> after, LinkedListNode<T> add)
{
if (after != null)
{
list.AddAfter(after, add);
}
else
{
list.AddFirst(add);
}
}
static LinkedListNode<T> NodeAt<T>(LinkedList<T> source, int index)
{
LinkedListNode<T> current = source.First;
while (index-- > 0)
{
current = current.Next;
}
return current;
}
}
, . , , , .
, , . , , , , , . , , .
:
class Program
{
static void Main(string[] args)
{
LinkedList<int> test = new LinkedList<int>(Enumerable.Range(0, 10));
ShuffleLinkedList(test);
Console.WriteLine(string.Join(", ", test));
}
static void ShuffleLinkedList<T>(LinkedList<T> list)
{
Random random = new Random();
for (int i = list.Count; i > 1; i--)
{
LinkedListNode<T> node = NodeAt(list, random.Next(i));
if (list.Last != node)
{
list.Remove(node);
list.AddLast(node);
}
}
}
static LinkedListNode<T> NodeAt<T>(LinkedList<T> source, int index)
{
LinkedListNode<T> current = source.First;
while (index-- > 0)
{
current = current.Next;
}
return current;
}
}
node.
, (O (n) O (n ^ 2)) , , :
class Program
{
static void Main(string[] args)
{
LinkedList<int> test = new LinkedList<int>(Enumerable.Range(0, 10));
Shuffle(test);
Console.WriteLine(string.Join(", ", test));
}
static void Shuffle<T>(LinkedList<T> source)
{
T[] choices = new T[source.Count];
for (int i = 0; i < choices.Length; i++)
{
choices[i] = source.First.Value;
source.RemoveFirst();
}
ShuffleArray(choices);
foreach (T choice in choices)
{
source.AddLast(choice);
}
}
static void ShuffleArray<T>(T[] array)
{
Random random = new Random();
for (int i = array.Length; i > 1; i--)
{
int j = random.Next(i);
if (i - 1 != j)
{
T t = array[i - 1];
array[i - 1] = array[j];
array[j] = t;
}
}
}
}