Пузырьковая сортировка и foreach

Запарился вчера реализовывать этот алгоритм и всё пытался понять, где же в этих трёх строках кода я ошибся, а оказывается ошибся кто-то другой :) Ну или не совсем я. Проблема в том, что после сортировки исходный массив чисел отличался от конечного отсортированного в том смысле, что сумма чисел исходного и конечного была разная. Потому что некоторые элементы массива дублировались и затирали собой другие. Вот типичный пример, где уже после второй итерации суммы масивов разнятся:
PHP:
array
  0 => int 81
  1 => int 38
  2 => int 9
  3 => int 57
  4 => int 20
  5 => int 81
  6 => int 78
  7 => int 68
  8 => int 79
  9 => int 55
  10 => int 72
  11 => int 18
  12 => int 9
  13 => int 16
  14 => int 61
  15 => int 57
  16 => int 35
  17 => int 98
  18 => int 44
  19 => int 96

81:81(0), 81:38(1),

int 1    // номер итерации $i
int 1029 // сумма элементов исходного массив
int 1072 // сумма элементов массива на текущей итерации

boolean false

array
  0 => int 38
  1 => int 9
  2 => int 38
  3 => int 57
  4 => int 20
  5 => int 81
  6 => int 78
  7 => int 68
  8 => int 79
  9 => int 55
  10 => int 72
  11 => int 18
  12 => int 9
  13 => int 16
  14 => int 61
  15 => int 57
  16 => int 35
  17 => int 98
  18 => int 44
  19 => int 96
А вот собственно код:
PHP:
define('LENGTH', 20);
$db = array();
for ($i = 0; $i < LENGTH; $i ++) {
    $db[] = rand(0, 100);
}

var_dump($db);
$checkSum = array_sum($db);
foreach ($db as $i => $value) {
// for ($i = 0; $i < LENGTH; $i ++) {
//     $value = $db[$i];

    echo $db[$i] . ':' . $value . '(' . $i . '), ' ;

    if (isset($db[$i + 1])) {
        if ($value > $db[$i + 1]) {
            $db[$i]     = $db[$i + 1];
            $db[$i + 1] = $value;
        }
    }

    // проверка контрольной суммы
    if (array_sum($db) != $checkSum) {
        var_dump(array($i, array_sum($db), $checkSum));
        break;
    }

    $j = $i;
    for ($j = $i; $j != 0; $j --) {
        if ($db[$j] < $db[$j - 1]) {
            $dbj        = $db[$j];
            $db[$j]     = $db[$j - 1];
            $db[$j - 1] = $dbj;
        } else {
            break;
        }
    }
}

var_dump($checkSum == array_sum($db), $db);
И если в этом коде закоментировать foreach и раскоментировать следующие за ним две строки т.е. перебрать массив через for, то всё отлично работает.
Если обратить внимание на вот этот вывод:
PHP:
81:81(0), 81:38(1),
, генерируемый кодом
PHP:
echo $db[$i] . ':' . $value . '(' . $i . '), ' ;
то видно, что даже после того, как я поменял 1-ый 81 на 2-ой 38 и теперь 38 - 1-ый, а 81 - 2-ой в $value конструкция foreach всё равно положит значение 38, хотя если обратиться ко 2-му элементу по индексу, то будет получено верное значение - 81.
Как так ? Что с foreach ?
 

Bardak

Новичок
Вы неправильно реализовали алгоритм.

foreach манипулирует не с самим массивом $db, а с его копией.

Для реализации пузырькового алгоритма сортировки используйте цикл while
 

tz-lom

Продвинутый новичок
foreach пробегается по копии массива, чтобы этого не было объявляй итератор как референс
PHP:
php > $a= array(1,2,3);
php > foreach($a as $i ) { echo $i; $a=array(); }
123
php > var_dump($a);
array(0) {
}
php > $a= array(1,2,3);
php > foreach($a as &$i ) { echo $i; $a=array(); }
1
php > var_dump($a);
array(0) {
}
php >
 
Bardak
что неправильного то ? Работает же, какая разница через for или while...
tz-lom
С использованием "&" тоже не работает.

Ну в принципе можно и принять тот факт, что foreach работает с копией, а не с самим массивом в качестве ответа. Спасибо.
 
Сверху