С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.84/76: Рейтинг темы: голосов - 76, средняя оценка - 4.84
1 / 1 / 0
Регистрация: 16.10.2011
Сообщений: 69

Объединение (конкатенация) двух односвязных списков

17.10.2011, 00:15. Показов 14230. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Задача: Построить стек (односвязный список). Показать реализацию стека на следующем примере: сцепить два связанных списка данных символьного типа, через функцию concatenate.
Списки ввожу до того момента, пока не введется '0'.
Вот то, что получилось:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
using namespace std;
 
struct node{
    char d;
    node *p;
};
node *first(char d);
void push(node **top, char d);
char pop(node **top);
node *concatenate(node **top, node **top2);
 
int main(){
    cout << "Введите 1й список" << endl;
    char t;
    cin >> t;
    node *top=first(t);
    cin >> t;
    while (t!='0'){
        push(&top,t);
        cin >> t;
    }
    cout << "Введите 2й список" << endl;
    cin >> t;
    node *top2=first(t);
    cin >> t;
    while (t!='0'){
        push(&top2,t);
        cin >> t;
    }
    node *res=concatenate(&top,&top2);
    while (res)
        cout << pop(&res) << ' ';
return 0;
}
node *first(char d){
    node *pv=new node;
    pv->d=d;
    pv->p=0;
    return pv;
}
void push(node **top, char d){
    node *pv=new node;
    pv->d=d;
    pv->p=*top;
    *top=pv;
}
char pop(node **top){
    char temp=(*top)->d;
    node *pv=*top;
    *top=(*top)->p;
    delete pv;
    return temp;
}
node *concatenate(node **top, node **top2){
    char temp;
    temp=pop(*&top2);
    node *pv=first(temp);
    while (top2){
        char temp2=pop(*&top2);
        push(&pv,temp2);
    }
    while (top){
        char temp2=pop(*&top);
        push(&pv,temp2);
    }
    return pv;
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.10.2011, 00:15
Ответы с готовыми решениями:

Объединение двух списков
Помогите пожалуйста с решением следующей задачи. Нужно добавить функцию для объединения двух списков. #include &lt;iostream&gt;...

Найти объединение двух списков
Помогите мне решить задачку, я в принципе не понимаю как её решать, вот её условие. Найти объединение двох списков,тоисть получить такой...

Объединение двух связанных списков (нужен совет)
шаблон ListNode #pragma once // оголошення, щоб зробити другом template&lt; typename NODETYPE &gt; class List; // шаблон класу ...

16
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,703
17.10.2011, 00:51
Допустим, первый список (схематично) из двух элементов
a->b
второй
c->e

У меня несколько вопросов: на что должен указывать b.p (и соответственно c.d) и каков должен быть конечный список (a->b->c->e или как? И если да, то на что должен указывать в таком случае e.d? )
0
1 / 1 / 0
Регистрация: 16.10.2011
Сообщений: 69
17.10.2011, 00:57  [ТС]
kravam, список должен состоять из a,b,c,e, что за b.p и c.d?
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,703
17.10.2011, 01:01
a->b->c->e?

Ну поля, ё. У тебя же d это указатель, на что он указывать должен?:

Добавлено через 1 минуту
struct node{
char d;
node *p;
};
а, ошибся я; p указатель на что должен указывать?
0
17.10.2011, 01:03

Не по теме:

Цитата Сообщение от kravam Посмотреть сообщение
а, ошибся я; p указатель на что должен указывать?
на следующий элемент в списке, кэп?=)
есть список a, есть список b.

создаем список с, в котором поочередно добавляем элементы списка a, затем элементы списка b, функция добавления есть,в чем проблема?

0
1 / 1 / 0
Регистрация: 16.10.2011
Сообщений: 69
17.10.2011, 01:07  [ТС]
kravam,
silentnuke, да, p - это следующий элемент

Добавлено через 3 минуты
Цитата Сообщение от silentnuke Посмотреть сообщение
создаем список с, в котором поочередно добавляем элементы списка a, затем элементы списка b, функция добавления есть,в чем проблема?
именно это и не получается реализовать в функции concatenate
0
Android Programmer
141 / 142 / 10
Регистрация: 08.12.2010
Сообщений: 421
17.10.2011, 01:17
Цитата Сообщение от SkyFlyStaR Посмотреть сообщение
kravam,
silentnuke, да, p - это следующий элемент

Добавлено через 3 минуты

именно это и не получается реализовать в функции concatenate
ну дык, у вас там вечный цикл, кто за вас будет смещать указатель на следующий элемент списка, Страуструп?
0
1 / 1 / 0
Регистрация: 16.10.2011
Сообщений: 69
17.10.2011, 01:24  [ТС]
silentnuke, не совсем пойму, где бесконечный цикл, я pop'ом достаю поочередно элементы из списков и push'ем помещаю в новый
0
Android Programmer
141 / 142 / 10
Регистрация: 08.12.2010
Сообщений: 421
17.10.2011, 01:38
Цитата Сообщение от SkyFlyStaR Посмотреть сообщение
silentnuke, не совсем пойму, где бесконечный цикл, я pop'ом достаю поочередно элементы из списков и push'ем помещаю в новый
да, мой косяк, не обратил что так делаете=)

Добавлено через 8 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
using namespace std;
 
struct node{
    char d;
    node *p;
};
node *first(char d);
void push(node **top, char d);
char pop(node **top);
node *concatenate(node **top, node **top2);
 
int main(){
    cout << "Введите 1й список" << endl;
    char t;
    cin >> t;
    node *top=first(t);
    cin >> t;
    while (t!='0'){
        push(&top,t);
        cin >> t;
    }
    cout << "Введите 2й список" << endl;
    cin >> t;
    node *top2=first(t);
    cin >> t;
    while (t!='0'){
        push(&top2,t);
        cin >> t;
    }
    node *res=concatenate(&top,&top2);
    while (res)
        cout << pop(&res) << ' ';
    return 0;
}
node *first(char d){
    node *pv=new node;
    pv->d=d;
    pv->p=0;
    return pv;
}
void push(node **top, char d){
    node *pv=new node;
    pv->d=d;
    pv->p=*top;
    *top=pv;
}
char pop(node **top){
    char temp=(*top)->d;
    node *pv=*top;
    *top=(*top)->p;
    delete pv;
    return temp;
}
node *concatenate(node **top, node **top2){
    char temp;
    temp=pop(top2);
    node *pv=first(temp);
    while (*top2!=NULL){
        char temp2=pop(top2);
        push(&pv,temp2);
    }
    while (*top!=NULL){
        char temp2=pop(top);
        push(&pv,temp2);
    }
    return pv;
}
1
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,703
17.10.2011, 02:20
silentnuke, дядя, я спрашивал за ПОСЛЕДНИЙ указатель. Куда бы он указывал у меня , я знаю. Куда он должен указывать у ТС- один Бог ведает. может у него закольцованный список.

Но как бы то ни было.

Введём:
C++
1
2
3
4
5
6
Введите 1й список
q
0
Введите 2й список
w
0
И пронализируем поведение программы. Для этого в функцию конкантекации добавим такие
надписи:
C++
1
2
3
4
5
6
7
8
9
10
         printf ("top2= %x\n", top2);
        temp=pop(*&top2);
        node *pv=first(temp);
 
        printf ("top2= %x\n", top2);
 
        while (top2){
                printf ("wwwwwwwwww\n");
                char temp2=pop(*&top2);
                printf ("rrrrrrrrrrrrr\n");
Теперь внимательно меня слушаем.
По запуску программы мы не увидим
C++
1
                printf ("rrrrrrrrrrrrr\n");
Делаем вывод, что сбой где-то во втором вызове pop. Действительно, первый вызов pop, вот этот
C++
1
2
3
4
5
        printf ("top2= %x\n", top2);
        temp=pop(*&top2);
        node *pv=first(temp);
 
        printf ("top2= %x\n", top2);
не вызвал сбоя, wwwwwwwwwww напечаталось
Но вызовы pop совершенно одинаковы! И даже передаются одинаковые адреса! Почему первый pop отрабатывает нормально, а второй даёт сбой?

Делаем предположение: Значит, между вызовами pop меняется СОДЕРЖАНИЕ адресов. Причём меняется АВАРИЙНО так, что второй pop не может сработать.
Где находится участок кода, в котором могло бы аварийно поменяться содержание адресов? (И этот участок должен находиться МЕЖДУ вызовами pop)

Правильно. Этот участок- сама функция pop. При её первом вызове что-то там нехорошее происходит.

Смотрим на функцию pop. Она принимает параметр top, равный top2, проверяем это, пишем так:
C++
1
2
char pop(node **top){
        printf ("top= %x\n", top);
Запускаем прогу и видим:
C++
1
2
3
4
5
6
7
8
9
10
11
Введите 1й список
q
0
Введите 2й список
w
0
top2= 22ff54
top= 22ff54
top2= 22ff54
wwwwwwwwww
top= 22ff54
ага, функция pop вызвалась 2 действительно, top==top2, адреса не меняются, значит меняется то, что лежит по этим адресам; при втором вызове pop даёт крах

Обращаю твоё внимание на одну очень важную вещь: мы убедились, что pop даёт крах при ВТОРОМ вызове, но исследовать будем ПЕРВЫЙ ВЫЗОВ, ибо, как мы поняли, именно в первый раз аварийно меняется содержимое top! (или top2, что то же самое)

Итак, пошли в функцию смотреть, что такого происходит с этим адресом:
C++
1
2
3
        char temp=(*top)->d;
//Тут вроде всё нормально, даже можем посмотреть чему равно становится temp 
//        printf ("temp= %c\n", temp);
////////////////////////////////////////////////////////
C++
1
        node *pv=*top;
Это уже интереснее. Содержимое top куда-то кладётся- а мы уже помним, что нас интересует именно содержимое этого адреса! Держим в уме переменную pv!


C++
1
        *top=(*top)->p;
Ага, *top это адрес объекта и он меняется! На корректное ли значение? Нет! Ведь (*top)->p указывает на ноль! ПРоверяем:
C++
1
2
3
4
5
6
7
8
9
10
char pop(node **top){
        printf ("top= %x\n", top);
        char temp=(*top)->d;
//        printf ("temp= %c\n", temp);
        node *pv=*top;
        *top=(*top)->p;
        printf ("__*top= %d\n", *top);
        delete pv;
        return temp;
}

Введите 1й список
q
0
Введите 2й список
w
0
top2= 22ff54
top= 22ff54
__*top= 0
top2= 22ff54
wwwwwwwwww
top= 22ff54


Ноль! А в следующий вызов pop мы также вызовем её со значением 22ff54. разыменуем и получим 0, с котрого безуспешно будем пытаться взять вот это:
C++
1
char temp=(*top)->d;
И вот тут-то и будет самый настоящий крах.
Ввыод: при первом вызове pop НЕПРАВИЛЬНО писать это:
C++
1
        *top=(*top)->p;
- читай: класть ноль в переменную p, ибо будет второй вызов, который обратится по адресу p, равному 0 и потерпит крах!

Добавлено через 16 минут
В обшем, я с самого начал хотел написать, что нужна функция вывода списка- щас бы проверили.
Короче, размышляя так. приходим к выводу, что эти условия неверны:
C++
1
2
while (top2)
while (top){
а надо так:

C++
1
2
while ((*top2))
while ((*top))
Запускаем, прога сбоев не даёт. Но и проверить конкантекацию возможности нет- ведь нет соответсвующей функции. Пиши. Пивет!

Добавлено через 3 минуты
НУ то есть мы делаем неправильно одно из двух: это
C++
1
        *top=(*top)->p;
или это

C++
1
while (top2)
ибо если условие не выполнялось, то ы бы и в функцию не вошли и краха бы не было.
Ну а дальше уж сам сообразишь что менять.
1
Android Programmer
141 / 142 / 10
Регистрация: 08.12.2010
Сообщений: 421
17.10.2011, 03:03
kravam, ошибка была в проверке, выше уже выложил решение.
0
0 / 0 / 0
Регистрация: 03.11.2011
Сообщений: 3
03.11.2011, 17:59
у меня похожая задача, но на Си: напишите программу, выполняющую конкатенацию двух связанных списков символов. программа должна включать функцию concatenate, которой в качестве аргументов передаются указатели на оба списка и она присоединяет второй список к первому.

Вот что я написал:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
 
struct listNode{
    char data;
    listNode *nextPtr;
};
 
typedef struct listNode LISTNODE;
typedef LISTNODE *LISTNODEPTR;
 
//funktsia obiedinenia spiskov
void concatenate(LISTNODEPTR , LISTNODEPTR );
//funktsia pechati spiska
void printList(LISTNODEPTR);
//funktsia vvoda bukv v spisok
void insert(LISTNODEPTR *, char);
 
void main(){
    clrscr();
    char item;
    LISTNODEPTR startPtr=NULL;
    LISTNODEPTR startPtr2=NULL;
    //vvodim 3 bukvi v pervii spisok
    for(int i=0;i<3;i++){
       printf("Enter a character list1: \n");
       scanf("%s", &item);
       insert(&startPtr, item);
       printList(startPtr);
    }
       //vvodim 3 bukvi vo vtoroi spisok
    for(i=0;i<3;i++){
       printf("Enter a character list2: \n");
       scanf("%s", &item);
       insert(&startPtr2, item);
       printList(startPtr2);
    }
    //obiedinenie
    concatenate(startPtr,startPtr2);
    printf("\nConcatenate list(1+2): \n");
    printList(startPtr);
    getch();
}
 
//funktia vvoda bukv v spisok
void insert(LISTNODEPTR *sPtr, char value){
    LISTNODEPTR newPtr, prevPtr, curPtr;
    newPtr=(LISTNODEPTR)malloc(sizeof(LISTNODE));
    if(newPtr!=NULL){
       newPtr->data=value;
       newPtr->nextPtr=NULL;
       prevPtr=NULL;
       curPtr=*sPtr;
       while(curPtr!=NULL&&value>curPtr->data){
          prevPtr=curPtr;
          curPtr=curPtr->nextPtr;
       }
       if(prevPtr==NULL){
          newPtr->nextPtr=*sPtr;
          *sPtr=newPtr;
       }
       else{
          prevPtr->nextPtr=newPtr;
          newPtr->nextPtr=curPtr;
       }
    }
    else
       printf("%c  not inserted. No memory avaible\n", value);
}
 
//funktia raspechatki spiska
void printList(LISTNODEPTR curPtr){
    if(curPtr==NULL)
       printf("List is empty\n");
    else{
       printf("The list is: \n");
       while(curPtr!=NULL){
          printf("%c-> ", curPtr->data);
          curPtr=curPtr->nextPtr;
       }
       printf("NULL\n\n");
    }
}
 
//funktia obiedinenia dvuh spiskov
void concatenate(LISTNODEPTR startPtr, LISTNODEPTR startPtr2){
    LISTNODEPTR curPtr;
    curPtr=startPtr;
    while(curPtr!=NULL){
       printf("%c-> ", curPtr->data);
       curPtr=curPtr->nextPtr;
    }
    if(curPtr->nextPtr==NULL) {
       curPtr->nextPtr=startPtr2;
    }
}
вроде правильно, но почему не объединяет - ума не приложу. подскажите пожалуйста, что не так?
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,703
03.11.2011, 19:25
Правило перое:
1) ты должен найти данные, на которых твоя программа спотыкается.

Правило второе:
2) ты должен упростить их до минимума

То есть, допустим программа спотыкается на списках (грубо говоря

2->3->4
3->5

В данном контектсе упростить- значит уменьшить списки до минимума- до одного или двух (естессно, программа должна продолжать виснуть)

И потом, если не найдушь ошибку говорить:
вот у меня список 1->2 и 1->NULL, не присоединяется ни фига. Согласись, гораздо проще работаь с маленькими данными, нежели с большими? И не говори, что программа всегда не присоединяет. Тут конкретика нужна.

Иначе всю эту подготовительную работу дожен будет проделать отвечающий (напрример, я), а меня с некоторых пор стало ломать это делать.
0
0 / 0 / 0
Регистрация: 03.11.2011
Сообщений: 3
03.11.2011, 19:59
Ок! я просто не знал, только что буквально зарегистрировался на форуме.

В программе все работает, но
проблема, мне кажется в функции объединения списков concatenate.
функция получает два указателя на начало первого списка (startPtr)и на начало второго списка (startPtr2).
Дальше в while я дохожу до конца первого списка, т.е. до указателя последнего узла первого списка, который равен NULL и в if присваиваю ему указатель на начало второго списка:
curPtr->nextPtr=startPtr2;

Присваивание происходит, т.к.проверял, распечатывается второй список.
Т.е., если я правильно понимаю, связывание двух списков произошло.

Потом в main запускаю функцию печати списка с параметром указателем на начало списка printList(startPtr) - печатается только первый список, а второй присоединенный -нет!

вот в этом и загвоздка. не могу понять почему.
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,703
03.11.2011, 20:07
Чё надо делать, я сказал.
0
0 / 0 / 0
Регистрация: 03.11.2011
Сообщений: 3
04.11.2011, 01:48
хмм.. че то не понятно, что от меня требуется
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,703
04.11.2011, 05:45
Правило перое:
1) ты должен найти данные, на которых твоя программа спотыкается.

Правило второе:
2) ты должен упростить их до минимума
...А я пока в упор не вижу чё надо вводить чтобы убедиться- да, вот конкантекации не происходит.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.11.2011, 05:45
Помогаю со студенческими работами здесь

Объединение двух списков в один без повтора элементов (С++)
нужно дописать функцию, которая делает из двух списков один (новый), в котором все элементы разные, то есть не повторяются. Спасибо! ...

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

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

Сортировка линейных(односвязных) списков
Всем доброго времени суток. Уже на протяжении нескольких дней бьюсь с сортировкой линейных списков. Вариант сортировки не важен, важно...

Чем отличается сортировка односвязных списков от сортировки двусвязных?
Чем отличается сортировка односвязных списков от двусвязных списков? Если можете то на примере объяснить (сортировка методом выбора...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru