Удаление из линейного однонаправленного списка.

Тема в разделе "WASM.BEGINNERS", создана пользователем Luna, 17 май 2010.

  1. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    Говорят, что существует множество способов удаления из списка. Вот один из них:
    Код (Text):
    1. void los::del_el()
    2. {
    3.  
    4.     int key;
    5.     los *q, *w, *e;
    6.     cout << "vvedite key: ";
    7.     cin >> key;
    8.     q=p;
    9.  
    10.  
    11.     while(q!=NULL && q->k!=key) q=q->next;
    12.  
    13.     if(q!=NULL && q->k==key) {
    14.  
    15.         if(q==p) {
    16.  
    17.             p=q->next;
    18.             delete(q);
    19.             q=p;
    20.             return;
    21.         };
    22.  
    23.  
    24.         w=p;
    25.         while(w->next!=q)
    26.            w=w->next;
    27.            w->next=q->next;
    28.            delete q;
    29.            }
    30.  
    31.  
    32.     clrscr();
    33.  
    34.  
    35. }
    А вы знаете ещё какие-нибудь методы удаления?????
     
  2. 7mm

    7mm New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2009
    Сообщения:
    442
    Говорят, что кур доят. А мы пошли, да сисек не нашли!
     
  3. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    Ладно, но хоть какая-то альтернатива этому варианту существует?...Может, можно путём сдвига убрать элемент:...выбрать ключ, на его место скопировать последний элемент и удалить последний элемент..?
     
  4. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    А слабо имея указатель на элемент односвязного списка, удалить этот элемент из списка не перебирая всех предыдущих?
     
  5. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    r90
    Это сложный путь..Есть пути полегче..???????
     
  6. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    Вот этот, например, вариант аналогичен исходному по алгоритму метода действия?
    Код (Text):
    1.  // удаление одного из участников по фамилии
    2.         puts("udalit 1 u4astnikov vvedite - 1");
    3.         scanf("%d",&ud);
    4.         if (ud==1)
    5.         {
    6.                 scanf("%s",&udal);
    7.                 puts("----------------------------------------------------");
    8.  
    9.                 printf("vi xotite udalit u4astnika s familiej: %s",udal);
    10.                 s1=first1;
    11.                 while (s1!=NULL && strcmp(udal,s1->fam)!=0)
    12.                 {
    13.                         ps1=s1;
    14.                         s1=s1->ptr;
    15.                 }
    16.  
    17.                 if (ps1!=NULL && s1!=NULL)
    18.                 {
    19.                         ps1->ptr=s1->ptr;
    20.                         delete s1;
    21.                 }
    22.                 else
    23.                         puts("familii nety");
    24.  
    25.  
    26.  
    27.         }
    28.         getch();
     
  7. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.561
    Адрес:
    Russia
    r90
    Так как нельзя трогать предыдущие - будем трогать следующие:
    Код (Text):
    1. typedef struct _Elem
    2. {
    3.     _Elem* next;
    4.     char testdata[200];
    5. } Elem;
    6.  
    7. void DeleteElem(Elem* node)
    8. {
    9.     Elem* next = NULL;
    10.     if (node != NULL)
    11.     {
    12.         next = node->next;
    13.         if (next != NULL)
    14.         {
    15.             memcpy(node, next, sizeof(Elem));
    16.             delete next;
    17.         }
    18.     }
    19. }
    А если подробнее, имеем список:
    []->[]->[]->[m]->[х]->[]->0
    m - элемент который нужно удалить. х - следующий элемент.

    Копируем следующий элемент в наш:
    []->[]->[]->[m]->[х]->[]->0
    ^___|
    Удаляем следующий элемент:
    []->[]->[]->[x]->[]->0

    Вот и все.
     
  8. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    TermoSINteZ
    а есть что-нибудь классическое?
     
  9. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.561
    Адрес:
    Russia
    Luna
    Что значит классическое ? Все алгоритмы работы с односвязными списками сводятся к работе с указателями. Поиск\вставка\удаление. Сортировки рассматриваются отдельно.
     
  10. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    TermoSINteZ
    Я имею ввиду удаление..Как ещё можно удалить элемент, кроме того, что написала я..???
     
  11. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.561
    Адрес:
    Russia
    Luna
    Я же вам показал как. Чем не понравилось?
     
  12. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    TermoSINteZ
    Объём кода мне нравится...;)Но вот эта функция memcpy(node, next, sizeof(Elem)) не внушает доверия, точнее- целиком всё выражение, а особенно- 3-й параметр....
    Этой функции к тому же нет в dos-м компиляторе (версии по-моему- 3.1)
     
  13. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    TermoSINteZ
    Ты знал! Так нечестно :)
    Luna
    Поищи как следует. Она должна быть там. В конце концов её можно написать. Надо просто скопировать элемент.
    Luna
    По результату да. А работает он несколько иначе. Одним путешествием по списку меньше. Надо полагать, что алгоритм другой.
     
  14. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    r90
    а зачем здесь sizeof(Elem)?

    Какой на ваш взгляд самый простой способ удаления?)
     
  15. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.561
    Адрес:
    Russia
    Luna
    Это чтобы узнать каков размер элемента списка. Яж в алгоритме описывал, что его необходимо скопировать (Весь).
    memcpy можете заменить на копирование вашего элемента вашими средствами (я же не знаю структуру вашего элемента который в списке). В крайнем случае сделайте так:
    Код (Text):
    1. inl_memcpy(void* pOut, void* pIn, unsigned long ulSize)
    2. {
    3.    __asm
    4.   {
    5.   pushad
    6.   mov esi,pIn
    7.   mov edi,pOut
    8.   mov ecx,ulSize
    9.   rep movsd
    10.   popad
    11.   }
    12. }
    Как то так :) ну или тупо циклом

    Код (Text):
    1. inl_memcpy(void* pOut, void* pIn, unsigned long ulSize)
    2. {
    3.     for(unsigned long i = 0; i < ulSize; i++)
    4.          pOut[i] = pIn[i];
    5. }
     
  16. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    TermoSINteZ
    Не покатит. Речь, насколько я понял, про DOS и 16-бит.
    У вас явно выраженное мышление ассемблерщика. Всё гораздо проще:
    Код (Text):
    1. Elem *dst, *src;
    2. ...
    3. *dst = *src;
     
  17. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.561
    Адрес:
    Russia
    r90
    Я просто старался человеку показать, что вообще и как делает функция memcpy и зачем там в третьем параметре sizeof.
     
  18. Luna

    Luna New Member

    Публикаций:
    0
    Регистрация:
    7 ноя 2009
    Сообщения:
    288
    TermoSINteZ
    r90
    Большое спасибо за примеры =)..но что-то с 1-го раза они не работают
     
  19. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    Еще вариант.

    Код (Text):
    1. typedef struct list_s {
    2.  
    3.     struct list_s *next;
    4.     struct list_s *prev;
    5.  
    6. } list_t;
    7.  
    8.  
    9. void  list_initialize(list_t *head)
    10. {
    11.     head->next = head;
    12.     head->prev = head;
    13. }
    14.  
    15. void  list_insert_tail(list_t *head, list_t *node)
    16. {
    17.     list_t *prev;
    18.  
    19.     prev = head->prev;
    20.  
    21.     node->next = head;
    22.     node->prev = prev;
    23.     prev->next = node;
    24.     head->prev = node;
    25. }
    26.  
    27. void  list_remove_node(list_t *head, list_t *node)
    28. {
    29.     list_t *next;
    30.     list_t *prev;
    31.  
    32.     next = node->next;
    33.     prev = node->prev;
    34.  
    35.     next->prev = prev;
    36.     prev->next = next;
    37. }
     
  20. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.561
    Адрес:
    Russia
    Microedition
    Это ж двунаправленный. Автору нужен однонаправленный :) Судя по названию темы.