Untitled

mail@pastecode.io avatar
unknown
abap
2 years ago
17 kB
4
Indexable
Never
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>



typedef struct Node
{
    int data; // поле данных
    struct Node* next; // указатель на следующий элемент списка
} Node;

//
int Menu();

void Append( Node** lst, int value ); // Swap( int* a, int* b )  Print( int val ); .... Print(a);
//
void InsertHead( Node** lst, int value );
//
void Print( Node* lst );
//
void DeleteTail( Node** lst );
//
int InList( Node* lst, int value );
// удалить элемент с начала списка
void DeleteHead( Node** lst );
// вставить новый элемент val после первого найденного значения sought
void InsertAfter( Node* lst, int sought, int val );

// вставить новый элемент val перед первым найденным значением sought
void InsertBefore( Node** lst, int sought, int val );

void Destroy( Node** lst );
//
void DeleteAfter( Node* lst, int sought );
//
void DeleteBefore( Node** lst, int sought );
// функция удаляет все чётные элементы из списка
void DeleteEven( Node** lst );
// функция меняет местами первый нечётный и последний чётный элементы 1 3 2 4 7 6 11
void SwapOddEven ( Node* lst );
//
void SwapMinMax( Node* lst );
//
int DeleteElem( Node** lst, Node* elem );
// функция возвращает указатель на последний чётный элемент
Node* GetLastEven( Node* lst );

int main()
{

    SetConsoleCP( 1251 );
    SetConsoleOutputCP( 1251 );

    Node* head = NULL;

    int key;
    do
    {
        key = Menu();

        switch ( key )
        {
        case 1:
        {
            int val;
            printf( "Введите элемент: " );
            scanf( "%d", &val );
            Append( &head, val );
            break;
        }
        case 2:
        {
            int val;
            printf( "Введите элемент: " );
            scanf( "%d", &val );
            InsertHead( &head, val );
            break;
        }

        case 3:
        {
            DeleteTail( &head );
            break;
        }

        case 4:
        {
            DeleteHead( &head );
            break;
        }

        case 5:
        {
            int val;
            printf( "Введите элемент: " );
            scanf( "%d", &val );
            if ( InList( head, val ) )
                puts( "Элемент в списке" );
            else
                puts( "Элемент НЕ найден" );
            break;
        }

        case 6:
        {
            Print( head );
            break;
        }

        case 7:
        {
            Destroy ( &head );
            break;
        }

        case 8:
        {
            int sought, val;
            printf( "\nВыберете элемент для поиска " );
            scanf( "%d", &sought );
            printf( "\nВведите элемент для вставки " );
            scanf( "%d", &val );
            InsertAfter( head, sought, val );
            break;
        }
        case 9:
        {
            int sought, val;
            printf( "\nВыберете элемент для поиска " );
            scanf( "%d", &sought );
            printf( "\nВведите элемент для вставки " );
            scanf( "%d", &val );
            InsertBefore( &head, sought, val );
            break;
        }
        case 10:
        {
            int sought;
            printf( "\nВыберете элемент, после которого удалить элемент " );
            scanf( "%d", &sought );
            DeleteAfter( head, sought );
            break;
        }
        case 11:
        {
            int sought;
            printf( "\nВыберете элемент, перед которым удалить элемент " );
            scanf( "%d", &sought );
            DeleteBefore( &head, sought );
            break;
        }
        case 12:
        {
            DeleteEven( &head );
            break;

        }
        case 13:
        {
            SwapOddEven ( head );
            break;
        }
        case 14:
        {
            SwapMinMax( head );
            break;
        }
        case 15:
        {
            Node* el = GetLastEven( head );
            if ( DeleteElem( &head, el ) )
                puts( "Последний чётный элемент успешно удалён" );
            else
                puts( "Чётных элементов в списке не найдено" );
            break;
        }

        }
    }
    while ( key != 0 );

    if ( NULL != head )
        Destroy ( &head );

    return 0;
}


int Menu()
{
    puts( "\n\nВыберете пункт меню" );
    puts( "1 - Добавить в конец списка" );
    puts( "2 - Добавить в начало списка" );
    puts( "3 - Удалить с конца списка" );
    puts( "4 - Удалить с начала списка" );
    puts( "5 - Найти элемент в списке" );
    puts( "6 - Распечатать весь список" );
    puts( "7 - Очистить список" );
    puts( "8 - Вставить после" );
    puts( "9 - Вставить до" );
    puts( "10 - Удалить после" );
    puts( "11 - Удалить до" );
    puts( "12 - Удалить все четные элементы" );
    puts( "13 - Поменять местами первый нечетный и последний четный элементы" );
    puts( "14 - Поменять местами min и max" );
    puts( "15 - Удалить последний четный элемент" );
    puts( "0 - Выход из программы" );

    int key;
    printf( "\nВыбор: " );
    scanf( "%d", &key );

    return key;
}

void Append( Node** lst, int value )
{
    Node* elem = ( Node* )malloc( sizeof( Node ) ); // Node* - тип elem - это указатель на новый элемент
    elem->data = value;
    //(* elem).data = value;
    elem->next = NULL;

    // если список пуст
    if ( *lst == NULL )
    {
        *lst = elem;
        return;
    }


    // если список не пустой
    Node* curr = *lst; // lst - адрес головы списка; *lst - адрес первого элемента списка (содержимое головы списка)
    while ( curr->next != NULL ) // curr->next == (*curr).next
        curr = curr->next;

    curr->next = elem;
}

// с правками
void InsertHead( Node** lst, int value )   // ** хотим менять значение, которое содержатся в head
{
    Node* elem = ( Node* )malloc( sizeof( Node ) ); // elem - указатель на новый элемент в списке, который хранит его адрес
    elem->data = value;

    // если список пустой
    if ( *lst == NULL )
        elem->next = NULL;
    else
        // если в спике есть хотябы один элемент
        elem->next = *lst;

    *lst = elem;
}

// 7 6 0 5 --> NULL , 12, 8
// 7 --> NULL, 7, 34
void InsertAfter( Node* lst, int sought, int value )
{

    while ( lst != NULL )
    {
        if ( lst->data == sought )
            break;

        lst = lst->next;
    }

    if ( lst == NULL )
        return;

    Node* elem = ( Node* )malloc( sizeof ( Node ) );
    elem->data = value;

    // Node* curr = lst->next; переписать без curr
    elem->next = lst->next;
    lst->next = elem;



}


void DeleteAfter( Node* lst, int sought )
{

    if ( lst == NULL || lst->next == NULL )
        return;

    Node* curr = lst;
    Node* post = lst->next;
    //1 2 3 4
    while ( post != NULL )
    {
        if ( curr->data == sought )
            break;

        curr = post;
        post = post->next;
    }

    if ( post != NULL )
    {
        curr->next = post->next;
        free( post );
    }
}

// 4
// 1 2 3 4 5
void DeleteBefore( Node** lst, int sought )
{

    if ( *lst == NULL || ( *lst )->next == NULL )
        return;

    // 6
    // 1 2 3 4 5 --> NULL
    Node* post = ( *lst )->next;
    if ( post->data == sought )
    {
        free( *lst );
        *lst = post;
        return;
    }


    post = post->next;
    Node* curr = *lst;
    while ( post != NULL )
    {
        if ( post->data == sought )
            break;

        curr = curr->next;
        post = post->next;
    }

    if ( post != NULL )
    {
        free( curr->next );
        curr->next = post;
    }
}



void DeleteEven( Node** lst )
{
    // 1) удаляем ВСЕ чётные элементы в начале списка
    Node* curr = *lst;
    while ( curr != NULL )
    {

        if ( curr->data % 2 != 0 ) // если встретили нечетный элемент,
            break; // то обрываем цикл, чтобы в голову списка записать адрес этого элемента

        Node* del = curr; // запоминаем в копию адрес элемента, который нужно удалить
        curr = curr->next; // переходим на следующий элемент списка
        free( del ); // удаляем текущий четный элемент
    }
    // на выходе из цикла в указателе curr будет либо NULL, либо адрес первого нечётного элемента в списке
    *lst = curr; // в голову списка запишем адрес из указателя сurr

    if ( *lst == NULL )
        return;


    Node* post = ( *lst )->next;
// 1 2 3 4 5 ->null
    while( post != NULL )
    {
        if ( post->data % 2 == 0 ) {
                 free( post );
            post = post->next;
            curr->next = post;



        }

        curr = curr->next;
        post = post->next;
    }

    if( post == NULL )
        return;

}


// сюда попадаем только тогда когда в голове списка находится нечетный элемент

/*
    if ( ( *lst )->next == NULL && ( *lst )->data % 2 == 0 ) {
        free( *lst );
        *lst = NULL;
        return;
    }

     Node* curr = *lst; // адрес первого элемента списка
       Node* post = ( *lst )->next;
       Node* odd = NULL, *even = NULL;

       while ( curr != NULL ) {

           if ( curr->data % 2 == 0 ) {

               free( curr );
               curr->next = post;
           }

           if ( curr->data % 2 != 0 )
               odd = curr;

           curr->next = post;
           post = post->next;

       }*/





void InsertBefore( Node** lst, int sought, int value )
{
    // 7 10
    // 5 6 7 11 --> NULL
    if ( *lst == NULL )
        return;

    if ( ( *lst )->data == sought )
    {
        Node* elem = ( Node* )malloc( sizeof ( Node ) );
        if ( elem != NULL )
        {
            elem->data = value;
            elem->next = *lst;
            *lst = elem;
        }
        return;
    }

    Node* curr = *lst, *post = ( *lst )->next;
    while ( post != NULL )
    {
        if ( post->data == sought )
            break;

        curr = post;
        post = curr->next;


    }
    //       10
    // 1 3 5   6 7 -> NULL
    //
    if ( post != NULL )
    {
        Node* elem = ( Node* )malloc( sizeof ( Node ) );
        if ( elem != NULL )
        {
            elem->data = value;
            elem->next = post;
            curr->next = elem;
        }
    }
}

// с правками
void DeleteTail( Node** lst )
{

    if ( *lst == NULL )
        return;

    // lst->next
    //
    if ( ( *lst )->next == NULL )   // если в списке есть один элемент
    {
        free( *lst );
        *lst = NULL;
        return;
    }

    Node *curr = *lst;
    // чтобы удалить элемент в конце списка необходимо пройти циклом до предпоследнего элемента
    // 5 --> 12 --> 15 --> 8 --> NULL
    while ( curr->next->next != NULL )
        curr = curr->next;

    free( curr->next );
    curr->next = NULL;
}

// с правками
void DeleteHead( Node** lst )
{

    if ( *lst == NULL ) // если список пустой
        return;

    if ( ( *lst )->next == NULL )   // если список содержит один элемент
    {
        free( *lst );
        *lst = NULL;
        return;
    }

    // если в списке больше одного элемента
    Node* second = ( *lst )->next; // записываем адрес второго элемента в указатель second
    free( *lst );
    *lst = second;
}

void Print( Node * lst )
{
    if ( lst == NULL )
    {
        puts( "\nСписок пуст" );
        return;
    }

    while ( lst != NULL )
    {
        printf( "%d ", lst->data );
        lst = lst->next;
    }

    return;
}

int InList( Node * lst, int value )
{
    while ( lst != NULL )
    {
        if ( lst->data == value )
            return 1;
        lst = lst->next;
    }

    return 0;
}

void Destroy( Node** lst )
{
    if ( *lst == NULL )
        return;

    if ( ( *lst )->next == NULL )   // если список содержит один элемент
    {
        free( *lst );
        *lst = NULL;

        return;
    }

    Node* curr = *lst; // адрес первого элемента списка
    Node* post = ( *lst )->next; // адрес второго/следующего элемента списка

    //9 --> NULL
    while ( post != NULL  )
    {
        free( curr );
        curr = post;
        post = curr->next;
    }

    free( curr );
    *lst = NULL;
}

void SwapOddEven( Node* lst )
{
    // 2 4 3 6 7 8 11 -> NULL
    // 2

    Node* odd = NULL, *even = NULL;
    while ( lst != NULL )
    {
        if ( lst->data % 2 != 0 && odd == NULL ) // если odd == NULL значит не находили нечетный элемент
            odd = lst; // если встретили первый нечетный элемент, то запоминаем его адрес

        if ( lst->data % 2 == 0 )
            even = lst;

        // 2 2 2 2 2 1
        lst = lst->next; // переход на следующий элемент списка в цикле
    }

    if ( odd != NULL && even != NULL )
    {
        int temp = odd->data;
        odd->data = even->data;
        even->data = temp;

    }

// после выполнения цикла адрес первого нечетного элемента остаётся в odd
}

void SwapMinMax( Node* lst )
{
    // 1 2 4 6 7 9 -> NULL

    if ( lst == NULL || lst->next == NULL )
        return;

    Node* curr = lst->next;
    Node* max = lst, *min = lst;

    while ( curr != NULL )
    {
        if ( curr->data > max->data )
            max = curr;

        if ( curr->data < min->data )
            min = curr;

        curr = curr->next;
    }
    if ( max != min )
    {
        int temp = min->data;
        min->data = max->data;
        max->data = temp;
    }

}

// 1 4 8 9 7 --> NULL

Node* GetLastEven( Node* lst )
{
    Node* elem = NULL;

    while ( lst != NULL )
    {
        if ( lst->data % 2 == 0 )
            elem = lst;

        lst = lst->next;
    }

    return elem;
}

// 3 5 9 4 7
int DeleteElem( Node** lst, Node* elem )
{

    if ( *lst == NULL || elem == NULL )
        return 0; // return 0 - ничего не удалено, а return 1 что-то удалено

    if ( *lst == elem )
    {
        *lst = ( *lst )->next;
        free( *lst ); // free(elem)
        return 1;
    }
    else
    {
        // попадаем в else, если в голове списка нет совпадения
        Node* curr = *lst;
        Node* post = ( *lst )->next;
        while ( post != NULL )
        {
            if ( post == elem )
                break;

            curr = curr->next;
            post = post->next;
        }

        if ( post != NULL )
        {
            curr->next = post->next;
            free( post );
            return 1;
        }
    }

    return 0;
}