назад до уроку

Вивести одинозв’язаний список

важливість: 5

Скажімо, у нас є одинозв’язаний список (як описано в розділі Рекурсія та стек):

let list = {
  value: 1,
  next: {
    value: 2,
    next: {
      value: 3,
      next: {
        value: 4,
        next: null
      }
    }
  }
};

Напишіть функцію printList(list), що виводить список елементів один за одним.

Зробіть два варіанти рішення: з використанням циклу та з використанням рекурсії.

Що краще: з рекурсією чи без неї?

Рішення на основі циклу

Варіант рішення на основі циклу:

let list = {
  value: 1,
  next: {
    value: 2,
    next: {
      value: 3,
      next: {
        value: 4,
        next: null
      }
    }
  }
};

function printList(list) {
  let tmp = list;

  while (tmp) {
    alert(tmp.value);
    tmp = tmp.next;
  }

}

printList(list);

Зверніть увагу, що ми використовуємо тимчасову змінну tmp, щоб пройти по списку. Технічно ми могли б використовувати замість нього параметр функції list:

function printList(list) {

  while(list) {
    alert(list.value);
    list = list.next;
  }

}

…Але це було б нерозумно. У майбутньому нам доведеться розширити функцію, зробити щось інше з list. Якщо ми змінюємо list, то ми втрачаємо таку здатність.

Говорячи про хороші імена змінних, list тут – це сам список. Його перший елемент. І це повинно залишитися так. Це ясно і надійний.

З іншого боку, tmp використовується виключно проходу, як i у for циклі.

Рішення через рекурсію

Рекурсивний варіант printlist(list) слідує простій логіці: вивести список, який ми повинні вивести поточний елемент list, а потім зробити те ж саме дляlist.next:

let list = {
  value: 1,
  next: {
    value: 2,
    next: {
      value: 3,
      next: {
        value: 4,
        next: null
      }
    }
  }
};

function printList(list) {

  alert(list.value); // виведіть поточний елемент

  if (list.next) {
    printList(list.next); // зробіть те ж саме для решти списку
  }

}

printList(list);

Що ж тепер краще?

Технічно цикл є більш ефективним. Ці два варіанти роблять те ж саме, але цикл не витрачає ресурси для вкладених викликів.

З іншого боку, рекурсивний варіант коротший, а іноді його легше зрозуміти.