Вывести на экран элементы, для которых сумма двух предыдущих элементов меньше двух следующих

Есть задания: а) Вывести на экран элементы, для которых сумма двух предыдущих элементов меньше двух следующих. А также вывести на экран эти суммы (код ниже, не выполняется) б) Вывести на экран элементы, для которых в списке предыдущих элементов количество парных равно количеству парных в списке следующих элементов.(хотелось бы посмотреть на алгоритм выполнения)

Касательно вопроса а), код:

void sumaparnyh(Tnum*& Start) {
    Tnum* wp, * pp, * xt;//xt=next-cлед.
    int  right, left, right1, left1;//числовые значения левого и правого соседа тек. элем.
    wp = Start;
    pp = NULL;
    xt = NULL;
    while (wp != NULL) {
        pp = wp->prev;
        xt = wp->next;
        if ((wp->next == wp->prev) && (wp->next == NULL)) {
            cout << "Only one element in list" << endl;
            break;
        }
        if (xt->next == NULL)
            right1 = 0;
        else right1 = xt->next->num;
        if (wp->next == NULL)
            right = 0;
        else right = wp->next->num;
        if (pp->prev == NULL)
            left1 = 0;
        else left1 = pp->prev->num;//если поставить точки остановы, то тут появляется картинка 1
        if (wp->prev == NULL)
            left = 0;
        else left = wp->prev->num;
        if (left + left1 < right + right1) {
            cout << "For " << wp->num << ": " << " summ of neighbor left " << left + left1 << " less than neigbor right" << right + right1 << endl;
        }
        pp = wp;
        wp = wp->next;
        xt = xt->next;
    }
}

Картинка 1

Работаю с двусвязным списком рандомных чисел. введите сюда описание изображения Крашится до выполнения. Ошибок код не выдает. В чем проблема? На выходе должны получится числа: элементы, у которых сумма предыдущих меньше, чем сумма следующих; эти же суммы.

Заранее спасибо за помощь!

Код всей программы:

#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
typedef
struct Num {
    int num;
    Num* prev;
    Num* next;
}Tnum;
void createRandList(Tnum*& Start, int cnt);
void addToEnd(Tnum*& Start, Tnum* PNew);
void addToSort(Tnum*& Start, Tnum* PNew);
void showList(Tnum*& Start);
void showControlOutputDbList(Tnum*& Start);
void delEl(Tnum*& Start);
void delList(Tnum*& Start);
int findPos(Tnum*& Start);
void dillnapyat(Tnum*& Start);
void dillnatri(Tnum*& Start);
void sumaparnyh(Tnum*& Start);

Tnum* Start;
void add(Tnum*& Start);

void createRandList(Tnum*& Start, int cnt)
{
    Tnum* PNew;
    srand(time(NULL));
    for (int i = 1; i <= cnt; i++)
    {
        PNew = new Tnum;
        PNew->num = rand() % 100;
        addToSort(Start, PNew);
    }
}

void addToEnd(Tnum*& Start, Tnum* PNew)
{
    Tnum* wp;
    PNew->next = NULL;
    PNew->prev = NULL;
    if (Start == NULL)
    {
        Start = PNew;
        return;
    }
    wp = Start;
    while (wp->next != NULL)
    {
        wp = wp->next;
    }
    wp->next = PNew;
    PNew->prev = wp;
}
void addToSort(Tnum*& Start, Tnum* PNew)
{
    Tnum* wp, * pp;
    PNew->next = NULL;
    PNew->prev = NULL;
    pp = NULL;
    wp = Start;
    while ((wp != NULL) && (PNew->num > wp->num))
    {
        pp = wp;
        wp = wp->next;
    }
    if (pp == NULL)
    {
        PNew->next = Start;
        if (Start != NULL)
        {
            Start->prev = PNew;
        }
        Start = PNew;
    }
    else
    {
        pp->next = PNew;
        PNew->prev = pp;
        if (wp != NULL)
        {
            wp->prev = PNew;
            PNew->next = wp;
        }
    }
}
void showList(Tnum*& Start)
{
    Tnum* wp = Start;
    while (wp != NULL)
    {

        cout << wp->num << " ";
        wp = wp->next;
    }
}
void showControlOutputDbList(Tnum*& Start)
{
    Tnum* wp, * pp;
    wp = Start;
    pp = NULL;
    while (wp != NULL)
    {
        cout << wp->num << " ";
        pp = wp;
        wp = wp->next;
    }
    cout << endl;
    wp = Start;
    while (pp != NULL)
    {
        cout << pp->num << " ";
        pp = pp->prev;
    }
    cout << endl;
}
void delEl(Tnum*& Start)
{
    int result = findPos(Start);
    Tnum* POld, * Prev, * Next;
    POld = Start;
    if (result > -1) {
        while (POld->num != result)
        {
            POld = POld->next;
        }
        Prev = POld->prev;
        Next = POld->next;
        if (Start == POld)
        {
            Start = Next;
            Start->prev = NULL;
        }
        else if (POld->next == NULL) {
            Prev->next = NULL;
        }
        else
        {
            Prev->next = Next;
            Next->prev = Prev;
        }
        delete POld;
    }
    else {
        cout << "Number wasn`t finded. You entered wrong number" << endl;
    }
}
void delList(Tnum*& Start)
{
    Tnum* POld;
    while (Start != NULL)
    {
        POld = Start;
        Start = Start->next;
        delete POld;
    }
}
int findPos(Tnum*& Start) {
    int num;
    cin >> num;
    Tnum* wp = Start;
    int pos = -1;
    while (wp != NULL) {
        if (wp->num == num) {
            pos = num;
            return pos;
        }
        wp = wp->next;
    }
}
void dillnapyat(Tnum*& Start) {
    if (Start == NULL) {
        return;
    }
    Tnum* wp;
    wp = Start;
    while (wp != NULL)
    {
        if (wp->num % 5 == 0)
        {
            if (wp->next == NULL)
            {
                wp->prev->next = NULL;
            }
            if (wp->next != NULL)
            {
                wp->prev->next = wp->next;
                wp->next->prev = wp->prev;
            }
        }
        wp = wp->next;
    }
    delete wp;
}
void dillnatri(Tnum*& Start) {
    Tnum* wp = Start;
    while (wp != NULL) {
        if (wp->num % 3 == 0 && wp->num >= 3) {
            if (wp->next == NULL) {
                Tnum* New = new Tnum;
                New->num = 10;
                New->next = NULL;
                New->prev = wp;
                wp->next = New;
            }
            else {
                Tnum* New = new Tnum;
                New->num = 10;
                New->next = wp->next;
                New->prev = wp;
                wp->next = New;
            }
        }
        wp = wp->next;
    }
}

/*void parnielementy(Tnum*&Start); это пункт б в моем вопросе, не готовый */

void sumaparnyh(Tnum*& Start) {
    Tnum* Left1, * Left, * Current, * Right, * Right1;
    int LeftSumm, RightSumm;
    Current = Start;
    if (Current->next == NULL)
    {
        cout << "Only one element in list" << endl;
        return;
    }
    else
        while (!Current) // то же самое, что (Current!=NULL)
        {
            Left = Current->prev;
            if (Left != NULL)
            {
                Left1 = Left->prev;
            }

            Right = Current->next;
            if (Right != NULL)
            {
                Right1 = Right->next;
            }
            // теперь здесь у вас указатели на 5 элементов списка
            // Если указатель == NULL, значит узла не существует
            // Дальше работаете со значениями узлов с предварительной проверкой указателей на NULL
            LeftSumm = 0;
            RightSumm = 0;
            if (!Left) // (Left != NULL)
            {
                LeftSumm += Left->num;
                if (!Left1)//Ошибка C4703 используется потенциально неинициализированная локальная переменная-указатель "Left1"
                {
                    LeftSumm += Left1->num;
                }
            }
            if (!Right)
            {
                RightSumm += Right->num;
                if (!Right1)//Ошибка C4703 используется потенциально неинициализированная локальная переменная-указатель "Right1"
                {
                    RightSumm += Right1->num;
                }
            }
            Current = Current->next;
            if (LeftSumm < RightSumm) {
                cout << "For " << Current->num << ": " << " summ of neighbor left " << LeftSumm << " less than neigbor right" << RightSumm << endl;
            }
            else cout << "Not found." << endl;
        }
}

void intList(Tnum*& Start) {
    Start = NULL;
}
int main()
{
    char ch;
    cout << "Choose operation with the list: \n";
    cout << "0. Fill the list with the random numbers\n";
    cout << "1. Show the list\n";
    cout << "2. Show the list in the forward and reverse order\n";
    cout << "3. Add element to the end of the list\n";
    cout << "4. Display elements, for which amount of previous paired elements equal amount of other paired elements\n";
    cout << "5. After all elements, which /3 paste 10\n";
    cout << "6. Delete list\n";
    cout << "7. Delete element\n";
    cout << "Protecting lab3: \n";
    cout << "8. Delete all elemets /5 \n";
    cout << "9. Display element, summ of neighbors of wich less summ next two. Show summ of this elements too\n";
    cout << "=============================================================================" << endl;
    do {
        cout << "\nEnter the number [0-9]: ";
        cin >> ch;
        switch (ch) {
        case '0': {int cnt;
            cout << "Enter the amount of elemetns: ";
            cin >> cnt;
            cout << endl;
            createRandList(Start, cnt);
            showList(Start); } break;
        case '1': showList(Start); break;
        case '2': showControlOutputDbList(Start); break;
        case '3': add(Start); break;
            /*case '4': parnielementy(Start);break; пункт б*/
        case '5': dillnatri(Start); break;
        case '6': {delList(Start); break;
            cout << "List deleted." << endl; }break;
        case '7': delEl(Start); break;
        case '8': dillnapyat(Start); break;
        case '9': sumaparnyh(Start); break;
        }
    } while (true);
    return 1;
}
void add(Tnum*& Start) {
    Tnum* PNew = new Tnum;
    cout << "You're going to add new number to the list. Number: "<<endl;
    cin >> PNew->num;
    addToEnd(Start, PNew);
    showList(Start);
}

Ответы (3 шт):

Автор решения: DmitryK

Вообще лучше привести весь текст программы. Т.к. ошибки могут быть и при заполнении списка. Но если сделать анализ по-быстрому, допустив что первоначальное формирование списка без ошибок, косячков много конечно.

  1. Зачем передавать в функцию указатель на ссылку (Tnum*& Start)? Я думаю, вы сами не понимаете смысл этой записи. Достаточно указателя.
  2. Проверку на 1 элемент в списке можно сделать один раз перед циклом, в самом начале.
  3. Проверка на 1 элемент в списке достаточно проверить на ноль указатель на следующий элемент и всё. В функцию передается указатель на начало списка, так? Если следующего элемента нет, значит список из 1 элемента:
wp = Start;
if (wp->next == NULL)
{
  cout << "Only one element in list" << endl;
  return;
}
  1. Крах программы из-за того, что вы обращаетесь по нулевому указателю. Нигде не проверяется указатели wp->prev и wp->next на NULL при переприсваивании. Если из цикла убрать ифы с подсчетом сумм значений, оставить только арифметику указателей, то получится:
while (wp != NULL) 
{
    pp = wp->prev;
    xt = wp->next;
    
    ... // здесь идет обращение по указателям

    pp = wp; // строчка бессмысленна, т.к. в начале цикла идет переопределение
    wp = wp->next;
    xt = xt->next; // строчка бессмысленна, т.к. в начале цикла идет переопределение
}

Т.е. если текущий элемент wp первый в списке, то pp становится равен NULL если текущий элемент wp последний в списке, xt становится равен NULL и дальше идет обращение pp->prev или xt->next, т.е. неизвестно куда.

while (wp != NULL) 
{
   pp = wp->prev; // если wp первый элемент, то pp == NULL
   xt = wp->next; // если wp последний элемент, то xt == NULL

   if ( pp->prev == NULL ) // вот здесь идет обращение в никуда
            left1 = 0;
   if ( xt->next == NULL ) // вот здесь идет обращение в никуда
            right1 = 0;

Хотя бы визуально отделите арифметику указателей от вычисления сумм. А ещё проще на каждом шаге цикла не проходить опять по указателям, а хранить в переменных (или массиве) значения 5 узлов списка и сдвигать их. Тогда на каждом шаге цикла нужно будет получить только 1 значение узла списка - самого правого (текущий+2).

→ Ссылка
Автор решения: DmitryK

У вас 2 указателя на предыдущие и 2 на последующие узлы списка. Их все нужно проверять на NULL. Для предыдующих:

if ( pp == NULL )
if ( pp->prev == NULL )

А для понимания механики процесса попробуйте сначала хранить указатели в отдельных переменных. И назовите их осмысленно. Также в самом начале помогает рисовать на бумаге, если не получается держать в голове. :) Например:

Tnum *Left1, *Left, *Current, *Next, *Next1; // указатели на 2 предыдущих, текущий и 2 следующих узла
int LeftSumm, RightSumm;
while(!Current) // то же самое, что (Current!=NULL)
{
  Left = Current->prev; 
  if(Left != NULL) 
  {
    Left1 = Left->prev;
  }

  Right = Current->next;
  if( Right != NULL )
  {
    Right1 = Right->next;
  }
  // теперь здесь у вас указатели на 5 элементов списка
  // Если указатель == NULL, значит узла не существует
  // Дальше работаете со значениями узлов с предварительной проверкой указателей на NULL
  LeftSumm = 0;
  RightSumm = 0;
  if(!Left) // (Left != NULL)
  {
    LeftSum += Left->num;
    if(!Left1)
    {
      LeftSum += Left1->num;
    }
  }

  ...
  
  Current = Current->next;
}


→ Ссылка
Автор решения: DmitryK

Вот так проверил - работает.
Поскольку Start - глобальная переменная, нет необходимости передавать её в параметрах функций.
Чтобы избавиться от закомментированных ошибок при инициализации указателей обнулите их.
И строка Current = Current->next; должна быть последней в теле цикла. Потому что это переход на следующий элемент списка.

Tnum* Start = NULL;

void createRandList(int cnt)
{
    Tnum* PNew;
    srand(time(NULL));
    for (int i = 1; i <= cnt; i++)
    {
        PNew = new Tnum;
        PNew->num = rand() % 100;
        addToSort(PNew);
    }
}

void showList(Tnum* Start)
{
    Tnum* wp = Start;
    while (wp != NULL)
    {
        cout << wp->num << " ";
        wp = wp->next;
    }
    cout << endl;
}

void delList(Tnum*& Start)
{
    Tnum* POld, *wp;
    wp = Start;
    while (wp != NULL)
    {
        POld = wp;
        wp = wp->next;
        delete POld;
    }
    Start = NULL;
}

void sumaparnyh(Tnum* Start) 
{
    Tnum *Left1=NULL, *Left, *Current, *Right, *Right1=NULL;
    int LeftSumm, RightSumm;
    Current = Start;
    if (Current->next == NULL)
    {
        cout << "Only one element in list" << endl;
        return;
    }
 
    while (Current!=NULL)
    {
        Left = Current->prev;
        if (Left != NULL)
        {
            Left1 = Left->prev;
        }

        Right = Current->next;
        if (Right != NULL)
        {
            Right1 = Right->next;
        }

        LeftSumm = 0;
        RightSumm = 0;
        if (Left != NULL)
        {
            LeftSumm += Left->num;
            if (Left1 != NULL)
            {
                LeftSumm += Left1->num;
            }
        }
        if (Right != NULL)
        {
            RightSumm += Right->num;
            if (Right1 != NULL)
            {
                RightSumm += Right1->num;
            }
        }
        
        if (LeftSumm < RightSumm) {
            cout << "For " << Current->num << ": " << " summ of neighbor left " << LeftSumm << " less than neigbor right " << RightSumm << endl;
        }
        else cout << "Not found." << endl;
        
        Current = Current->next;
    }
}


int main()
{
   createRandList(10);
   showList( Start );
   sumaparnyh( Start );
   delList( Start );
   
   return 0;
}
→ Ссылка