равномерно произвольный доступ к коллекции

Я хочу реализовать равномерно случайный доступ к определенной коллекции с N числами, так как каждый элемент в коллекции будет доступен с одинаковой вероятностью 1/N. Я поместил все элементы в измененный двойной связанный список. затем циклически сдвигайте его со случайным временем, удаляйте последний элемент, а затем добавляйте его как первый. наконец, выберите первый элемент. Я использовал его, чтобы проверить, сколько вызовов потребуется, чтобы охватить весь элемент, не удаляя элемент из списка. Общее необходимое количество мин постоянно на единицу меньше, чем ожидалось. Хотите знать, действительно ли реализация равномерно случайна? как вы думаете, моя реализация действительно случайна? Я отлаживал это в течение довольно долгого времени, но до сих пор не понял.

public Item callout(){
       for (int j=0; j<StdRandom.uniform(N); j++)
        {
            this.addFirst(this.removeLast()); 
// circular shift the queue by StdRandom.uniform(N)times, always return the first item;
        }
       return first.item;
   } 

public void addFirst(Item item){
   Node<Item> oldfirst = first;
   first = new Node<Item>();
   first.item = item;
   first.previous = null;

if (last == null) 
       {last = first;  first.next = null;} //if it's the first element added.   if last.next = null == last = null;!!!! 
   else 
   {
       first.next = oldfirst;
       oldfirst.previous = first;
   }
    N++;
 }

public Item removeLast(){
 if (last == null) throw new RuntimeException();
 Item item = last.item;


 // if right now only one element exists in the container
  if (first == last)
 {
   first=null;
   last=null;
 }

 else{
 last =last.previous;
 last.next = null;   
 // old first becomes first;    optional operation, easy way to tell if it's the header.
 }
   N--;

 return item;
 }

Следующий класс вычисляет количество вызовов, необходимых для достижения всеобъемлющего вызова, он получает RandomCollection с n элементами в нем. По сути, это коллекция с целыми числами от 1 до N, я использую массив флагов int [] для пометки, если элемент ранее вызывался.

private static int getNumberOfCallsForComprehensiveCallout(RandomCollection<Integer> test, int n){
    // create an array of the same number of items in collection, each with a Flag indicating whether it has beeen called
    int calltimes =0;     // calltimes stands for the numofcalls needed to reach a comprehensive call
    int flag = 1;     // flag used to indicate if this item has been called
    int [] c = new int [n];
      Arrays.fill(c, flag);
      int NumberOfFlags = n;


    while(NumberOfFlags != 0){
        int numbercalled = test.callout();
        if (c[numbercalled-1]==1) {NumberOfFlags--; c[numbercalled-1]=0;}
        else;   // indicate this item has been called earlier.
        calltimes++;
    //  System.out.println(calltimes);

    }
    return calltimes;   // return the number of calls for comprehensive callout each time this method is called.
}

person sthbuilder    schedule 10.02.2014    source источник
comment
Разметка кода устарела. В чем проблема?   -  person pauluss86    schedule 10.02.2014
comment
макет изменен. Я хочу реализовать равномерно произвольный доступ к определенной коллекции, я помещаю все элементы в измененный двойной связанный список. затем круговой сдвиг, всегда выбирайте первый элемент, чтобы проверить, сколько вызовов потребуется, чтобы охватить весь элемент, не удаляя элемент из списка. Общее необходимое количество мин меньше, чем предполагалось. Хотите знать, действительно ли реализация равномерно случайна? как вы думаете, моя реализация действительно случайна?   -  person sthbuilder    schedule 10.02.2014
comment
"случайность" - хитрая штука. Принимая во внимание исправление Нишанта, это зависит от чисел, сгенерированных StdRandom.uniform(N). Обратите внимание, что «настоящего случайного» действительно добиться трудно; Когда люди говорят о «генераторах случайных чисел» (ГСЧ), они часто имеют в виду псевдо генераторы случайных чисел (ГСЧ). Хороший PRNG кажется случайным, но его последовательность полностью определяется начальным начальным значением. Это полностью зависит от предполагаемого использования, является ли «случайный» достаточно случайным. Вам могут быть интересны «крепкие» тесты на случайность, если вы хотите знать, насколько случайным является ваш код.   -  person pauluss86    schedule 10.02.2014


Ответы (1)


Общая логика вроде бы верна, но -

Во-первых, количество вызовов для покрытия всех элементов (с заменой) может быть больше, чем размер коллекции. Infact это будет больше в большинстве случаев.

Во-вторых, в callout() вызовите метод StdRandom.uniform(N) вне цикла только один раз. попробуйте следующее изменение -

public Item callout(){
    int randomRotate = StdRandom.uniform(N);
    for (int j = 0; j < randomRotate; j++)
    {
        this.addFirst(this.removeLast()); 
    }

    return first.item;
}

Я провел несколько симуляций, и количество вращений распределяется неравномерно, если вызов StdRandom.uniform(N) выполняется внутри цикла for. Результаты гистограммы для коллекции размером 10 -

   0    1    2    3    4    5    6    7    8    9 
1001 1813 2074 2043 1528  902  454  144   37    4  
person Nishanth    schedule 10.02.2014
comment
Я полностью понимаю вашу точку зрения. второй блок исходного кода — это то, что я использовал для вычисления количества вызовов, необходимых для достижения комплексных вызовов. Любая проблема, как вы думаете? На мой взгляд, метод довольно понятен. Меня беспокоит то, что выноска не посещала элементы равномерно случайным образом, вы думаете, что это случайно? - person sthbuilder; 10.02.2014
comment
Количество оборотов определенно неравномерно. Проверьте мой второй пункт. - person Nishanth; 10.02.2014
comment
Вот Это Да! ты сделал мой день. и ваш способ проверить, является ли это случайным, меня тоже вдохновляет! огромное спасибо. - person sthbuilder; 10.02.2014
comment
Интересно построить гистограмму: ссылка. Определенно выглядит знакомо; вместо равномерного вы сделали распределение Гаусса (?) :-) - person pauluss86; 10.02.2014
comment
Интересно! выглядит как комбинация логарифмически нормального и экспоненциального распределения. - person Nishanth; 10.02.2014