Опубликован: 02.02.2011 | Уровень: для всех | Доступ: свободно
Лекция 30:

Динамические структуры данных: однонаправленные и двунаправленные списки

< Лекция 29 || Лекция 30: 12345 || Лекция 31 >

Удаление элемента из двунаправленного списка

Из динамических структур можно удалять элементы, так как для этого достаточно изменить значения адресных полей. Операция удаления элемента из двунаправленного списка осуществляется во многом аналогично удалению из однонаправленного списка ( рис. 29.6).

Удаление элемента из двунаправленного списка

Рис. 29.6. Удаление элемента из двунаправленного списка
/*удаление элемента с заданным номером из двунаправленного списка*/
Double_List* Delete_Item_Double_List(Double_List* Head, 
      int Number){
  Double_List *ptr;//вспомогательный указатель
  Double_List *Current = Head;
  for (int i = 1; i < Number && Current != NULL; i++)
    Current = Current->Next;
  if (Current != NULL){//проверка на корректность
    if (Current->Prior == NULL){//удаляем первый элемент
      Head = Head->Next;
      delete(Current);
      Head->Prior = NULL;
      Current = Head;
    }
    else {//удаляем непервый элемент
      if (Current->Next == NULL) {
      //удаляем последний элемент
        Current->Prior->Next = NULL;
        delete(Current);
        Current = Head;
      }
      else {//удаляем непервый и непоследний элемент
        ptr = Current->Next;
        Current->Prior->Next =Current->Next;
        Current->Next->Prior =Current->Prior;
        delete(Current);
        Current = ptr;
      }
    }
  }
  return Head;
}

Поиск элемента в двунаправленном списке

Операция поиска элемента в двунаправленном списке реализуется абсолютно аналогично соответствующей функции для однонаправленного списка. Поиск элемента в двунаправленном списке можно вести:

а) просматривая элементы от начала к концу списка;

б) просматривая элементы от конца списка к началу;

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

//поиск элемента в двунаправленном списке
bool Find_Item_Double_List(Double_List* Head, 
    int DataItem){
  Double_List *ptr; //вспомогательный указатель
  ptr = Head;
  while (ptr != NULL){//пока не конец списка
    if (DataItem == ptr->Data) return true; 
    else ptr = ptr->Next;
    }
  return false;
}

Проверка пустоты двунаправленного списка

Операция проверки двунаправленного списка на пустоту осуществляется аналогично проверки однонаправленного списка.

//проверка пустоты двунаправленого списка
bool Empty_Double_List(Double_List* Head){
  if (Head!=NULL)  return false;
  else  return true;  
}

Удаление двунаправленного списка

Операция удаления двунаправленного списка реализуется аналогично удалению однонаправленного списка.

//освобождение памяти, выделенной под двунаправленный список
void Delete_Double_List(Double_List* Head){
  if (Head != NULL){
    Delete_Double_List(Head->Next);
    delete Head;
  } 
}

Пример 1. N -натуральных чисел являются элементами двунаправленного списка L, вычислить: X1*Xn+X2*Xn-1+...+Xn*X1. Вывести на экран каждое произведение и итоговую сумму.

Алгоритм:

  1. Создаём структуру.
  2. Формируем список целых чисел.
  3. Продвигаемся по списку: от начала к концу и от конца к началу в одном цикле, перемножаем данные, содержащиеся в соответствующих элементах списка.
  4. Суммируем полученные результаты.
  5. Выводим на печать

Создание структуры, формирование списка и вывод на печать рассмотрены ранее. Приведем функции для реализации продвижения по списку в обоих направлениях и нахождения итоговой суммы.

//поиск последнего элемента списка
Double_List* Find_End_Item_Double_List(Double_List* Head){
  Double_List *ptr; //дополнительный указатель
  ptr = Head;
  while (ptr->Next != NULL){
    ptr = ptr->Next;
  }
  return ptr;
}

//итоговая сумма произведений
void Total_Sum(Double_List* Head) {
  Double_List* lel = Head;
  Double_List* mel = Find_End_Item_Double_List(Head);
  int mltp,sum=0;
  while(lel != NULL) {
    mltp = (lel->Data)*(mel->Data);//умножение элементов 
    printf("\n\n%d * %d = %d",lel->Data,mel->Data,mltp);
    sum = sum + mltp;//суммирование произведений 
    lel = lel->Next; 
    //идем по списку из первого элемента в последний
    mel = mel->Prior; 
    //идем по списку из последнего элемента в первый
  }
  printf("\n\n Итоговая сумма равна %d",sum);
}

Ключевые термины

Двунаправленный (двусвязный) список – это структура данных, состоящая из последовательности элементов, каждый из которых содержит информационную часть и два указателя на соседние элементы.

Длина списка – это величина, равная числу элементов в списке.

Линейный список – это список, отражающий отношения соседства между элементами.

Однонаправленный (односвязный) список – это структура данных, представляющая собой последовательность элементов, в каждом из которых хранится значение и указатель на следующий элемент списка.

Пустой список – это список нулевой длины.

Связанный список – это структура, элементами которой служат записи одного формата, связанные друг с другом с помощью указателей, хранящихся в самих элементах.

Список – это упорядоченное множество, состоящее из переменного числа элементов, к которым применимы операции включения, исключения.

Указатель начала списка (голова списка) – это указатель на первый элемент списка.

Краткие итоги

  1. Список является динамической структурой, для элементов которого определены операции включения, исключения.
  2. В связанном списке элементы линейно упорядочены указателями, входящими в состав элементов списка.
  3. Линейные связные списки являются простейшими динамическими структурами данных и в зависимости от организации связей делятся на однонаправленные и двунаправленные.
  4. В однонаправленном (односвязном) списке каждый из элементов содержит информационную часть и указатель на следующий элемент списка. Адресное поле последнего элемента имеет значение NULL.
  5. Каждый элемент списка содержит ключ, который идентифицирует этот элемент.
  6. Основными операциями с однонаправленными списками, являются: создание списка; печать (просмотр) списка; вставка элемента в список; удаление элемента из списка; поиск элемента в списке; проверка пустоты списка; удаление списка.
  7. В двунаправленном (двусвязном) списке каждый из элементов содержит информационную часть и два указателя на соседние элементы.
  8. Основные операции, выполняемые над двунаправленным списком, те же, что и для однонаправленного списка.
< Лекция 29 || Лекция 30: 12345 || Лекция 31 >
Денис Курбатов
Денис Курбатов
Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!