2016-05-06 3 views
0

Метод собирается удалить город для наименьшего населения!Может ли кто-нибудь объяснить, как работает этот метод?

Метод:

public void delCity(long population) { 
    if (population== 0) { 
     System.out.println("There is no city!"); 
     return; 
    } 

    for (int i = 0; i < index; i++) { 
     if (cities[i].getPopulation() < population) { 
      for (int j = i; j < index - 1; j++) { 
       cities[j] = cities[j + 1]; 
      } 
      cities[--index] = null; 
      i--; 
     } 
    } 
} 

Так что часть я не понимаю, тело второго для цикла, в примере, как cities[j] = cities[j + 1]; работает и что делает cities[--index] = null; i--;? Я был бы очень признателен за ваши ответы.

+2

Нет, этот метод удаляет все города с населением под заданным лимитом. Кстати, он делает это очень неэффективно (O (N²)) и должен быть запрещен. –

+0

Lol и как бы вы закодировали этот метод? –

+0

В одном цикле пакет слева содержит все элементы. –

ответ

5

Этот цикл сдвигает все значения массива [с позиции i, то есть города для удаления].(Поскольку массив является статическим, в противном случае существует нуль между элементами)

for (int j = i; j < index - 1; j++) { 
    cities[j] = cities[j + 1]; 
} 

Затем устанавливает последний элемент в нуль и уменьшение индекса;

cities[--index] = null; 

Вот из объяснений смещения: enter image description here enter image description here

Как уже упоминалось в комментариях. Ваша сложность - O (N²). Но просто изменяя структуру данных (например, используя списки), вы можете улучшить ее до O (N).

+0

Спасибо за освещение моей проблемы :) –

+0

@ VigKilla, кроме того, просто изменив вашу структуру данных, например, используя списки. Вы можете улучшить свою сложность до O (n) вместо O (n^2) – granmirupa

+0

«Этот цикл смещает все значения массива» ... Из фактического положения, в котором находится город с населением ниже порога. – antorqs

2
cities[j] = cities[j + 1]; 

выше оператор устанавливает город на индекс j в город по индексу j + 1.

cities[--index] = null; 

Это утверждение просто устанавливает последний индекс городов в null.

Как таковой, нет удаления элемента. Элемент, который нужно удалить, просто перезаписывается следующим элементом. И цикл делает это для всех элементов, следующих за тем, который нужно удалить. В конце мы остаемся с последним элементом, который установлен в null.

Оставляя пояснения в сторону, код довольно неэффективен.

+0

Спасибо за ответ, но почему он неэффективен? –

+1

Как упоминалось в одном из комментариев, он имеет сложность O (n²). Это связано с тем, что вы используете цикл вложенных циклов. –

0

index - размер массива cities. Итак, когда вы приходите к конкретной позиции, где cities[i].getPopulation() < population является true, вы будете двигаться все города с позиции i + 1 до конца массива index - 1 на позиции i в index - 2, и сделать это с:

for (int j = i; j < index - 1; j++) { 
       cities[j] = cities[j + 1]; 
      } 

Итак, город с небольшая популяция в позиции i, теперь j, будет удалена путем переопределения ее citiescities[j + 1], а citiescities[j + 1] будет переопределяться citiescities[j + 2] и т. д. до конца массива. Так, на позиции citiescities[index - 2] будет такой же, как citiescities[index - 1], поэтому мы должны удалить его, так что вы поместите cities[--index] = null;, где index будет первым уменьшенное (вот почему -- будет влево от index), и cities[oldIndex - 1] будет null. Это также поможет с циклом for не доходить до первого значения index значение в массиве, но до последнего города в array, то есть.

Теперь, поскольку ваш индекс i будет увеличен в следующем шаге цикла, но вы переместили следующий город в положение i, вы должны уменьшить i, чтобы проверить этот город, вот почему i в конце.

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

+1

'index - это предположение о размерах городов массива? – Nfear

+0

да, на основе этого: for (int i = 0; i cities.length это приведет к исключению ... поэтому я предполагаю, что размер массива ... или по крайней мере индекс <города .length ... –

+0

Спасибо за ваш ответ. –

1

Я прокомментировал код, поскольку более подробное объяснение было бы излишним в таком простом контексте.

//Scan all the cities, from i = 0 to i = index -1 
for (int i = 0; i < index; i++) 
{ 
    //Check it cities[i] has LESS population than specified 
    if (cities[i].getPopulation() < population) 
    { 
     //We need to remove cities[i] 
     //We shift all the subsequent cities 
     //(cities[i+1], cities[i+2], ... cities[index-1] one position LEFT, 
     //thereby overwriting cities[i] and so deleting it 

     //Shift all the subsequent cities left 
     //We start this for FROM i, so the first iteration is 
     //cities[i] = cities[i + 1]; 
     //The second is 
     //cities[i + 1] = cities[i + 2]; 
     //and so on. We STOP AT index - 2 (note the strict less than) 
     //So that j + 1 is AT MOST index - 1 
     for (int j = i; j < index - 1; j++) 
     { 
       cities[j] = cities[j + 1]; 
     } 

     //Since j was at most index - 2, the cities[index - 1] was not 
     //overwritten with the next one. Naturally as there is no next one 
     //for it. 
     //This last city is now duplicated (the copy is at index - 2) and 
     //Must be overwritten with null. 
     //Also index, which keep track of the number of cities must be 
     //decremented (here the pre-decrement -- is used) 
     cities[--index] = null; 

     //cities[i] was the deleted city. But now it contains cities[i + 1] 
     //Which is a totally different city! 
     //If we continue the for now, we will go to the NEXT city, as i 
     //will be incremented, to keep i the same one more iteration, we 
     //decrement it. This way we process (the new) cities[i] one more time. 
     i--; 
    } 
} 

Используйте старый карандаш и резину, пока вы полностью не поймете алгоритм, на самом деле нет лучшего способа.

+0

Спасибо, я буду. –

+0

У меня вопрос, поэтому мы получили массив из пяти элементов String [] array = {a, b, c, d, x}; и я хочу удалить x, поэтому используя предыдущий массив (его в for-loop) [i] = array [i + 1]; означает, что первый элемент (a) будет заменен следующим элементом (b): array [0] = array [1]; ? –

+0

Код 'array [i] = array [i + 1]' выполняется только с позиции * x *. Поэтому, если вы хотите удалить * x *, то No, * a * не будут заменены. Ничто не будет заменено, так как внутренний цикл сдвинет элемент до * d * максимум (так что для * x * он не будет циклически работать один раз). –

Смежные вопросы