我有一个函数,可以删除双向链表中最小的节点,但是如果有多个相同值的整数,这个函数会删除第一个,我需要做的是,这个函数会删除所有最小的值。
我想我需要做一个循环,检查链表中的所有值,如果它们是==到最小的值,就删除它们。
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
struct node *prev;
int number;
struct node *next;
} node;
node *createList(struct node *head, int n);
node *addToEmpty(node *head, int data);
node *addAtEnd(node *head, int data);
node *deleteSmallest(node *head, int n);
void cleanUp(node *head);
int main()
{
node *head = NULL;
node *ptr;
int n;
printf("Enter number of the nodes: ");
scanf("%d", &n);
head = createList(head, n);
printf("\nN: %d\n\n", n);
ptr = head;
while(ptr != NULL)
{
printf("NUMBER:%d ADDRESS:%p PREVADD:%p NEXTADD:%p\n", ptr->number, ptr, ptr->prev, ptr->next);
ptr = ptr->next;
}
head = deleteSmallest(head, n);
printf("\n\n");
ptr = head;
while(ptr != NULL)
{
printf("NUMBER:%d ADDRESS:%p PREVADD:%p NEXTADD:%p\n", ptr->number, ptr, ptr->prev, ptr->next);
ptr = ptr->next;
}
// Free all the pointers
cleanUp(head);
return 0;
}
node *createList(struct node *head, int n)
{
int data;
if(n <= 0)
return head;
printf("Enter number of the 1 node: ");
scanf("%d", &data);
head = addToEmpty(head, data);
for(int i = 1; i < n; ++i)
{
printf("Enter number of the %d node: ", i + 1);
scanf("%d", &data);
head = addAtEnd(head, data);
}
return head;
}
node *addToEmpty(node *head, int data)
{
node *temp = malloc(sizeof(node));
temp->prev = NULL;
temp->next = NULL;
temp->number = data;
head = temp;
return head;
}
node *addAtEnd(node *head, int data)
{
node *temp, *tp;
temp = malloc(sizeof(node));
temp->prev = NULL;
temp->next = NULL;
temp->number = data;
tp = head;
while (tp->next != NULL)
tp = tp->next;
tp->next = temp;
temp->prev = tp;
return head;
}
node *deleteSmallest(node *head, int n)
{
node *smallest, *temp, *temporaryHead;
int position = 1;
temporaryHead = head;
smallest = head;
// Finding which node has the smallest int
for(int i = 1; temporaryHead != NULL; ++i)
{
temp = temporaryHead->next;
if(smallest->number > temporaryHead->number)
{
smallest = temporaryHead;
position = i;
}
temporaryHead = temp;
}
temporaryHead = NULL;
temp = head;
// If node is in the middle
if(position > 1 && position < n)
{
while (position > 1) {
temp = temp->next;
--position;
}
temporaryHead = temp->prev;
temporaryHead->next = temp->next;
temp->next->prev = temporaryHead;
free(temp);
temp = NULL;
}else if(position == 1) // If node is the first element
{
head = head->next;
free(head->prev);
head->prev = NULL;
}else // If node is the last element
{
while(temp->next != NULL)
temp = temp->next;
temporaryHead = temp->prev;
temporaryHead->next = NULL;
free(temp);
temp = NULL;
}
return head;
}
void cleanUp(node *head)
{
node *next;
while(head != NULL)
{
next = head->next;
free(head);
head = next;
}
}
3条答案
按热度按时间qf9go6mv1#
我想我需要做一个循环,检查链表中的所有值,如果它们是==到最小的值,就删除它们。
我不太理解当前函数的逻辑(特别是
n
参数)。下面的函数允许只删除一个元素或 * 所有 * 匹配的最小元素。如果 * 只有 * 一个元素,则为单次扫描。如果有更多元素,则为两次扫描:
更新日期:
希望你已经得到了基本问题的答案。
但是,正如其他人所指出的,如果你 * 只 * 向前遍历一个 * 双向 * 链表,那么它有什么意义呢?
下面是一个更新的版本。它使用一个单独的
list
结构体并传递一个指向该结构体的指针,而不是传递head
并总是返回更新的值。下面是示例输入:
以下是示例输出:
cwxwcias2#
我将把逻辑分成几部分:
deleteSmallest
以下是可能的情况:
aamkag613#
如果你关心的是性能,你可以用
addToFront()
代替addAtEnd()
,这样可以减少从O(n^2)
到O(n)
输入数字的渐近时间。如果你必须一次又一次地删除最小值,链表并不是一个很好的选择。正如你所观察到的,如果你想找到最小值,就必须遍历所有的输入,每次都需要
O(n)
。在这种情况下,binary heap允许O(log n)
删除最小值。它通过heapify
来完成这一点,其中堆是通过在O(n)
中筛选来创建的。并且保持每个int
的堆属性小于或等于int
的孩子。我使用了我的implementation of a binary heap,我试着让它变得很标准,这和heapsort的功能很接近。