найти наименьшие два узла в связанном списке в c

0

Я пытаюсь найти наименьшие два числа в связанном списке в C++ (без использования встроенных функций).

Я попытался сделать так, как показано ниже:

Моя логика:

(1) Предположим, что первый узел в связанном списке minimum1 а второй - minimum2. Сравните их. Чем больше значение minimum2 тем меньше становится minimum1.

(2) Начните с третьего узла (третий, потому что мы уже рассмотрели первый и второй) в цикле while, пока не достигнем NULL, таким образом пройдя весь список.

(3) Сравните недавно пройденный узел с minimum1 и minimum2. Если этот узел меньше minimum1, тогда его значение minimum1. minimum2 теперь будет содержать значение minimum1, а minimum1 будет содержать значение только что найденного узла, который меньше, чем minumum1.

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

Код

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>

struct node
{
    int freq;
    struct node* next;
};
typedef struct node node;
node* tree;

// Finding minimum two elements:
void find_two_min(node** List, node** lmin1, node** lmin2)
{
    int i;
    node* temp = *List;
    node *min1, *min2;
    node* var1 = *List;
    node* second = (*List)->next;
    if (var1 > second)
    {
        min2 = var1;
        min1 = second;
    }
    else
    {
        min1 = var1;
        min2 = second;
    }
    while (temp->next->next->next != NULL)
    {
        if (temp->freq < min2->freq)
        {
            min1 = min2;
            min2 = temp;
        }
        else if (temp->freq < min1->freq)
        {
            min1 = temp;
        }
        temp = temp->next;
    }
    *lmin1 = min1;
    *lmin2 = min2;
}

void main()
{
    int size, data;
    node *min1, *min2;
    int count = 0; // This flag is to check whether it the first node inside the do-while loop.
    tree = NULL;
    printf("Enter the number of nodes:\n");
    scanf("%d", &size);
    printf("Enter the elements:\n");
    node* prev;
    do
    {
        scanf("%d", &data);
        if (count == 0)
        {
            node* temp;
            temp = (node*) malloc(sizeof(node));
            temp->freq = data;
            temp->next = NULL;
            prev = temp;
            tree = prev;
        }
        else
        {
            node* temp;
            temp = (node*) malloc(sizeof(node));
            temp->freq = data;
            temp->next = NULL;
            prev->next = temp;
            prev = prev->next;
        }
        --size;
        ++count;
    }
    while (size > 0);

    printf("Printing linked list:\n");
    node* temp1;
    temp1 = tree;
    while (temp1 != NULL)
    {
        printf("%d, ", temp1->freq);
        temp1 = temp1->next;
    }
    node* temp5 = tree;
    find_two_min(&temp5, &min1, &min2);
    printf("\nThe two minimum numbers are min1: %d and min2: %d.\n", min1->freq, min2->freq);
}

Мой код не работает на следующем входе (он дает неправильный вывод):

Enter the number of nodes:
4
Enter the elements:
0
-5
-2
8
Printing linked list:
0, -5, -2, 8,
The two minimum numbers are min1: 0 and min2: -5.

Предполагалось напечатать "min1: -5" и "min2: -2", но я не знаю, почему это не так.

Может ли кто-нибудь помочь мне устранить эту проблему? Любой алгоритм или фрагмент кода в C/C++ для использования в качестве ссылки оценен. Благодарю.

Примечание. Я не могу использовать встроенные функции.

  • 0
    1. Сортировка списка в порядке возрастания. Первые два узла будут вашими минимумами.
  • 1
    @ThomasMatthews: сортировка - это O(N . log N) то время как его логика решает это в O(N) , или я что-то здесь упускаю?
Теги:
algorithm
data-structures

6 ответов

1
Лучший ответ

Имейте два ints min1, min2, и INT_MAX (from limits.h). (Предположение: ни один элемент не может иметь значение INT_MAX.)

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


Если он меньше min1, то min1 теперь второй по величине, поэтому назначьте min1 в min2. Затем замените min1 на элемент.
Если он не меньше min1, но меньше min2, он заменяет min2.
Если ни один из вышеперечисленных, пропустите элемент.


После итерации списка min1 будет содержать наименьшее значение списка, min2 - второе наименьшее. Если min2 - INT_MAX, список имеет только один элемент. Если min1 является INT_MAX, список пуст.

  • 0
    Спасибо, это сработало, но все еще не знаю, почему мы присвоили INT_MAX для min1 и min2? Что они содержат? Я пытался гуглить, но не мог этого понять. что он делает, знаете ли вы другие альтернативы для достижения той же цели?
  • 1
    При поиске min логично инициализировать ваши временные переменные так, чтобы все остальные значения были меньше, гарантируя, что min вышел из списка, а не ваша инициализация. Подумайте, что произойдет, если вы инициализировали min1 для INT_MIN
Показать ещё 2 комментария
2

У вас есть ошибка в строке

if(var1>second)

Это сравнивает адреса памяти двух узлов, а не их частоты!

Там еще одна ошибка в строке

    if(temp->freq<min2->freq)

и более поздняя строка

    else if(temp->freq<min1->freq)

Код внутри блока if следующий за первой строкой, ведет себя так, как если бы вы сравнивали temp->freq с min1->freq, а не min2->freq как вы сейчас делаете, и наоборот для кода внутри else if блок-блок после второй строки.

2

Если вы пытаетесь сделать 2 вещи сразу же смущает вас,

то делать только 1 вещь,

И ПОЗЖЕ, следуйте за этим другим необычным усилием.

т.е.

1-й - напишите search1(), чтобы найти наименьший элемент и записать указатель узла.

2nd - напишите search2(), чтобы найти наименьший элемент, но добавьте к поиску2 идею сравнить адрес узла с ранее найденным наименьшим узлом. И когда он уже найден, пропустите его, как будто его там даже не было.


Внедрите search1, отлаживайте его и заработайте.


ПОСЛЕ ЭТОГО

Внедрите search2 (возможно, копию) и передайте указатель узла, найденный в search1. Каждый раз, когда вы обнаружите возможное обновление для самого маленького узла search2, вставьте тест, чтобы определить, совпадает ли этот узел с ранее найденным

  • 0
    Я просто пытался сделать то, что вы сказали (находя отдельно), но я все еще выдает неправильный вывод. Два минимальных числа: min1: -1074189952 и min2: -5
  • 0
    Итак, вы не смогли найти min1. Если вы не знаете отладчик, попробуйте использовать выходные данные (через cout или cerr) для отладки вашего кода.
1

Я выполнил решение своего вопроса, используя INT_MAX. Он отлично работает:

#include <stdio.h> 
#include <stdlib.h> 
#include <malloc.h>
#include <string.h> 
#include <limits.h>

struct node 
{
    int freq;
    struct node * next;
};
typedef struct node node;
node * tree;

//Problem creating area is below (code for finding minimum two elements)
void find_two_min(node * * List, node * * lmin1, node * * lmin2) 
{
    node * temp = * List;
    node * min1;
    min1 = (node*) malloc(sizeof(node));
    min1 -> freq = INT_MAX;
    node * min2;
    min2 = (node*) malloc(sizeof(node));
    min2 -> freq = INT_MAX;  //This initialisation of INT_MAX to min2->freq creates problem because printf() statment above it works well but don't work below it.
    printf("check1\n");
    while (temp != NULL) 
    {
        printf("\ncheck2\n");       
        if ((temp) -> freq < min2 -> freq)
        {
            printf("check3\n");
            min1 = min2;
            min2 = temp;
        } 
        else if ((temp) -> freq < min1 -> freq && (temp) -> freq != min2 -> freq)
        {
            printf("check4\n");
            min1 = temp;
        }
        temp = temp -> next;
    }
    * lmin1 = min1; 
    * lmin2 = min2;
    printf("address of min2 is : %d  and value is %d \n" ,min2, min2->freq);    
    printf("check5\n"); 
}
//Problem creating area is above//
void main() 
{
    int size, data;
    node * min1;
    node * min2;
    int count = 0; //this count flag is to check is it first node or not inside the do-while loop.
    tree = NULL;
    printf("enter the size of node\n");
    scanf("%d", & size);
    printf("start entering the number of elements until your size\n");
    node * prev;
    do {
        scanf("%d", & data);
        if (count == 0)
        {
            node * temp;
            temp = (node * ) malloc(sizeof(node));
            temp -> freq = data;
            temp -> next = NULL;
            prev = temp;
            tree = prev;
        }
        else 
        {
            node * temp;
            temp = (node * ) malloc(sizeof(node));
            temp -> freq = data;
            temp -> next = NULL;
            prev -> next = temp;
            prev = prev -> next;
        }
        size--;
        ++count;
    }
    while (size > 0);

    printf("Printing linked list\n");
    node * temp1;
    temp1 = tree;
    while (temp1 != NULL) 
    {
        printf("%d-> ", temp1 -> freq);
        temp1 = temp1 -> next;
    }
    node * temp5 = tree;
    find_two_min( & temp5, & min1, & min2);
    printf("\n The two minimum numbers are  min1 :%d   and min2 : %d\n", min1 -> freq, min2 -> freq);

}
1

Это должно сделать это:

#include <stdio.h> 
#include <stdlib.h> 
#include <malloc.h> 
#include <string.h>

struct node {
    int freq;
    struct node* next;
};
typedef struct node node;

//Function Prototype
void find_two_min(node**, node**, node**);

void main() {
    node* min1 = (node*) malloc(sizeof(node));
    node* min2 = (node*) malloc(sizeof(node));
    node* tree = NULL;
    node* prev;
    node* temp1;
    node* temp;
    node* temp5 = tree;
    int size, data;
    int count = 0; //this count flag is to check is it first node or not inside the do-while loop.
    printf("enter the size of node\n");
    scanf("%d", &size);
    printf("start entering the number of elements until your size\n");
    do {
        scanf("%d", & data);
        if (count == 0) {
            temp = (node*) malloc(sizeof(node));
            temp->freq = data;
            temp->next = NULL;
            prev = temp;
            tree = prev;
        } else {
            node* temp;
            temp = (node*) malloc(sizeof(node));
            temp->freq = data;
            temp->next = NULL;
            prev->next = temp;
            prev = prev->next;
        }
        size--;
        ++count;
    } while (size > 0);
    printf("Printing linked list\n");
    temp1 = tree;
    while (temp1) {
        printf("%d-> ", temp1->freq);
        temp1 = temp1->next;
    }
    if (count > 1) {
        find_two_min(&tree, &min1, &min2);
        printf("\n The two minimumnumbers are  min1 :%d   and min2 : %d\n",min1->freq,min2->freq);
    } else
        printf("\n Not enough data\n\n");

}

//Function Definition
void find_two_min(node** List,node** lmin1,node** lmin2) {
    node* temp = *List;
    node* min1;
    node* min2;
    node* var1 = *List;
    node* second=(*List)->next;

    /* OLD ONE    
    if (var1->freq > second->freq) {
      min2 = var1;
      min1 = second;
    } else {
      min1 = var1;
     min2 = second;
    }
   */

   if (var1->freq > second->freq) {
      min1 = var1;
      min2 = second;
    } else {
      min2 = var1;
     min1 = second;
    }
    while(temp->next) {
        printf("\nCurrent freq is %d", temp->freq);
        printf("\nNext freq is %d", (temp->next)->freq);

        if ((temp->next)->freq < min2->freq) {
            printf("\n  Condition one is fulfilled");
            min1 = min2;
            min2 = temp->next;    
        } else if ((temp->next)->freq < min1->freq) {
            printf("\n  Condition two is fulfilled");
            min1 = temp->next;
        }
        temp = temp->next;
    }
    *lmin1 = min1; 
    *lmin2 = min2;
}
  • 0
    Спасибо, но также извините, он не работает на следующем входе: "-1-> 0-> -5-> 2->" вывод "Два минимальных числа - min1: 0 и min2: -5", что неверно ,
  • 0
    О, это было в вашем коде, ха-ха. Исправлена.
1

У меня нет полного ответа для вас, но я не доверяю проверке temp->next->next->next!=NULL в цикле while. Это будет иметь проблемы с короткими списками.

Возможно, вам будет лучше смотреть на один предмет за раз. Задайте два минимальных значения максимально возможного значения (например, INT_MAX), а указатели узла - NULL.

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

У вас должен быть ваш ответ, когда вы дойдете до конца списка, а манипуляция указателем будет легче отслеживать/отлаживать.

  • 0
    спасибо, но я не мог понять, не могли бы вы рассказать подробнее?
  • 1
    В какой части я хочу уточнить?
Показать ещё 7 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню