Ваш список ссылок выглядит следующим образом:
На этом изображении prev находится объект перед объектом, который вы хотите удалить.Cur - это объект, который вы хотите удалить.
Вы зацикливаетесь, пока следующий указатель не нацелится на объект, который вы хотите удалить.После этого вы устанавливаете следующий указатель prev на объект, который следует за cur (cur - это объект, который вы хотите удалить).
В псевдокоде это будет выглядеть так:
prev = head;
while(prev.next != cur) {
prev = prev.next
}
После этого шага предыстория находится в правильном положении.
Вы можете видеть, что этот алгоритм работает с каждым случаем, кроме удаления головы.Вы можете проверить, удаляете ли вы голову и используете другой алгоритм или используете фиктивный узел.Используйте dummy-узел в качестве головы, а dummy-узел - в качестве хвоста (здесь не отображается, но используется в списках с двойными связями).Эти фиктивные узлы называются часовыми.Вы никогда не удалите этого стража, но ваш алгоритм работает без дополнительной проверки, потому что вы удалите элементы> 0.
Источники: https://www.cs.cmu.edu/~adamchik/15-121/lectures/Linked%20Lists/linked%20lists.html
В комментариях я видел обсуждение очистый код.Если вы изучаете чистый код, вы увидите, что многие алгоритмы легче понять, если переменные выражают свое назначение.Например, N должно быть размером.Но в другом контексте это может быть верхний предел элементов для кэша.На эту тему есть хорошая книга: Чистая архитектура: Руководство мастера по структуре и дизайну программного обеспечения (серия Роберта С. Мартина)
Как вы думаете, что легче читать:
int[][] a = new int[100][200];
for(int i = 0; i < a.length) {
for(int j = 0; j < a[i].length) {
a[i][j] = i*j;
}
}
или это:
int[][] productOfRowColumns = new int[100][200];
for(int row = 0; i < productOfRowColumns.length) {
for(int column = 0; j < productOfRowColumns[row].length) {
productOfRowColumns[row][column] = row*column;
}
}