我想问一下,如何在C中以恒定时间将两个未排序的列表合并到一个未排序的列表中,因为我们需要一个while循环来获取所有元素。
前:
List1: 2 5 1 4 3
List2: 5 9 4 2 5 7 8
List3: elements of the two lists,don't care about order
不要判断我是初学者。
答案 0 :(得分:1)
这取决于内存中的数据结构以及是否可以修改现有列表。
如果您可以修改现有列表,那么您可以向List1
询问它的最后一个元素(其中O(1)是列表标题具有指向列表末尾的指针)和那么它只是List1->last->next = List2->head
的问题。之后,迭代List1
将迭代所有元素。
如果您不能更改List1
,则必须复制列表;这对于O(1)来说很棘手,但是如果将所有元素保存在单个内存区域中(例如,您不使用指向节点的指针;而是将所有节点保留在数组中),这仍然是可能的。在这种情况下,您为两个列表的节点分配内存,然后您可以将结果填充两次memcopy()
。当然,memcopy()
并非真的是O(1)但是当前的CPU(可以每秒复制千兆字节),你通常不会注意到差异。
答案 1 :(得分:1)
tl; dr:去阅读有关链表数据结构的内容。所有这些都很常见。
真正的O(1)追加的最低要求是你有可变链接列表,可以持续访问尾部。
因此,最简单的链表是:
struct ListNode {
struct ListNode *next;
int data; /* or void*, or whatever */
};
typedef struct ListNode *SinglyLinkedList;
即,只需按住指向列表第一个元素的指针即可。在这种情况下,到达尾部是线性时间(O(n)
),因此您无法做到您想要的。但是,如果我们使用
struct ListHeadTail {
struct ListNode *head;
struct ListNode *tail;
/* could keep length here as well, if you want it */
};
然后插入列表会稍微困难一些,但您可以轻松地进行常量时间追加:
struct ListHeadTail append(struct ListHeadTail *first,
struct ListHeadTail *second) {
struct ListHeadTail result;
/* special cases first, where either first or second is empty */
if (first->head == NULL) {
result = *second;
second->head = second->tail = NULL;
} else if (second->head == NULL) {
result = *first;
first->head = first->tail = NULL;
} else {
result.head = first->head;
result.tail = second->tail;
first->tail->next = second->head;
first->head = first->tail = NULL;
second->head = second->tail = NULL;
}
return result;
}
其他常见结构是双向链表 - 再次使用标记节点而不是head->prev == tail->next == NULL
。
答案 2 :(得分:0)
如果你想要的是表现作为连接列表的东西,你可以通过创建一个由两个现有List类构造的ConcatenatedList类来实现。如果你使用的是纯C而不是C ++,那么类的概念可能需要稍微捏一下,但从结构上来说,这个想法是一样的。
ConcatenatedList类可以有两个属性:一个头属性,它只不过是对第一个List的引用,以及一个tail属性,它只不过是对第二个List的引用。
然后使用ConcatenatedList模拟基本List类的方法。要访问ConcatenatedList的第k个元素,可以尝试以下方法:
if (k < header->size()) {
return header->getElement(k);
}
return tail->getElement(k - header->size());
编码的其余部分应该是直接的。
使用这种方法,连接过程将是O(1)。
值得注意的是,(not)Useless提供的答案也是有效的,但它假定了列表的LinkedList结构,而这种方法没有这个要求。但是,在重复连接之后,这种方法在性能方面将开始看起来像LinkedList实现。