Я пытаюсь найти наименьшие два числа в связанном списке в 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++ для использования в качестве ссылки оценен. Благодарю.
Примечание. Я не могу использовать встроенные функции.
Имейте два 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, список пуст.
У вас есть ошибка в строке
if(var1>second)
Это сравнивает адреса памяти двух узлов, а не их частоты!
Там еще одна ошибка в строке
if(temp->freq<min2->freq)
и более поздняя строка
else if(temp->freq<min1->freq)
Код внутри блока if
следующий за первой строкой, ведет себя так, как если бы вы сравнивали temp->freq
с min1->freq
, а не min2->freq
как вы сейчас делаете, и наоборот для кода внутри else if
блок-блок после второй строки.
Если вы пытаетесь сделать 2 вещи сразу же смущает вас,
то делать только 1 вещь,
И ПОЗЖЕ, следуйте за этим другим необычным усилием.
т.е.
1-й - напишите search1(), чтобы найти наименьший элемент и записать указатель узла.
2nd - напишите search2(), чтобы найти наименьший элемент, но добавьте к поиску2 идею сравнить адрес узла с ранее найденным наименьшим узлом. И когда он уже найден, пропустите его, как будто его там даже не было.
Внедрите search1, отлаживайте его и заработайте.
ПОСЛЕ ЭТОГО
Внедрите search2 (возможно, копию) и передайте указатель узла, найденный в search1. Каждый раз, когда вы обнаружите возможное обновление для самого маленького узла search2, вставьте тест, чтобы определить, совпадает ли этот узел с ранее найденным
Я выполнил решение своего вопроса, используя 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);
}
Это должно сделать это:
#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;
}
У меня нет полного ответа для вас, но я не доверяю проверке temp->next->next->next!=NULL
в цикле while. Это будет иметь проблемы с короткими списками.
Возможно, вам будет лучше смотреть на один предмет за раз. Задайте два минимальных значения максимально возможного значения (например, INT_MAX
), а указатели узла - NULL.
У вас должен быть ваш ответ, когда вы дойдете до конца списка, а манипуляция указателем будет легче отслеживать/отлаживать.
O(N . log N)
то время как его логика решает это вO(N)
, или я что-то здесь упускаю?