合并两个LinkedList而不创建新的LinkedList
Merge two LinkedList without creating a new LinkedList
我正在尝试获取可执行文件中的两个链表,并将它们在交替位置合并。例如ListOne 1,2,3和ListTwo 4,5新的ListOne应该是1,4,2,5,3。
LinkedList.h文件:
class LinkedList
{
private:
struct ListNode
{
string firstName;
string lastName;
long int phoneNumber;
struct ListNode *next;
};
ListNode *head;
public:
LinkedList()
{
head = nullptr;
}
~LinkedList();
void appendNode(string f, string l, long int p);
void displayList();
};
LinkedList.cpp文件:
LinkedList::~LinkedList()
{
cout << "LinkList destructor" << endl;
}
void LinkedList::appendNode(string f, string l, long int p)
{
ListNode *newNode;
ListNode *nodePtr;
newNode = new ListNode;
newNode -> firstName = f;
newNode -> lastName = l;
newNode -> phoneNumber = p;
newNode -> next = nullptr;
if (!head)
head = newNode;
else
{
nodePtr = head;
while (nodePtr -> next)
//while nodePtr is pointing to another node
nodePtr = nodePtr -> next;
//move to that node
nodePtr -> next = newNode;
//inset the newNode at the end of the linked list
}
}
void LinkedList::displayList()
{
ListNode *nodePtr;
nodePtr = head;
while(nodePtr)
//while nodePtr is true, meaning there is a node in the list
{
cout << nodePtr -> firstName << endl;
cout << nodePtr -> lastName << endl;
cout << nodePtr -> phoneNumber << endl;
nodePtr = nodePtr -> next;
}
}
可执行文件:
LinkedList ListOne;
LinkedList ListTwo;
ListOne.appendNode("Cate", "Beckem", 7704563454);
ListOne.appendNode("Cabe","Tomas", 7703451523);
ListTwo.appendNode("Mary", "Smith", 4043456543);
ListTwo.appendNode("Mark", "Carter", 4045433454);
我的程序运行得很好,包括displayList函数。我只是很困惑如何去做一个合并函数。
LinkedList LinkedList::merge(LinkedList b)
{
// if one list is null, return the other
if (this->head == nullptr)
return b;
if (b.head == nullptr)
return *this;
LinkedList newlist;
ListNode *ap = this->head, *bp = b.head, *p = nullptr;
// if two pointer is all not null, move node from these to new list in turn
while (ap != nullptr && bp != nullptr)
{
if (newlist.head == nullptr)
{
p = newlist.head = ap;
ap = ap->next;
p = p->next = bp;
bp = bp->next;
}
else
{
p = p->next = ap;
ap = ap->next;
p = p->next = bp;
bp = bp->next;
}
}
// maybe one list is longer, and there is some node left.
if (ap != nullptr)
p->next = ap;
if (bp != nullptr)
p->next = bp;
//clear original list
this->head = b.head = nullptr;
//if you want to merge list b to the caller list, you can change to
//this->head = newlist->head and beginning part also need some modification.
return newlist;
}
也许您不想更改原始列表,那么您可以复制值并为新列表创建新节点。
合并是将已从源列表复制或将从源列表被盗的节点插入到目标列表的特定位置。
我假设您希望在该操作中将源列表视为不可变的,因此源节点将被复制。
对复制和插入操作都有用的是迭代器,它指向一个节点,在++
之后,op指向列表中或列表末尾后面的下一个节点(相当于nullptr
):
(我在单个源文件中编写这样的代码段;将实现移动到.cpp文件或内联它们)
//
#include <type_traits>
using std::conditional;
#include <stdexcept>
using std::runtime_error;
class LinkedList
{
private:
// [...]
template <bool const_tag>
struct NodeIterator {
using element_type = typename conditional<
const_tag,
const ListNode,
ListNode
>::type;
using pointer_type = element_type*;
using reference_type = element_type&;
static const NodeIterator end;
NodeIterator(pointer_type p_in = nullptr) : p(p_in) {}
NodeIterator& operator++ () {
if (nullptr == p)
throw runtime_error("Attempt to dereference nullptr");
this->p = p->next;
return *this;
}
bool operator== (const NodeIterator& rhs) const {
return this->p != rhs.p;
}
bool operator!= (const NodeIterator& rhs) const {
return !(*this == rhs);
}
pointer_type operator->() const {
return p;
}
reference_type operator*() const {
if (nullptr == p)
throw runtime_error("Attempt to dereference nullptr");
return *p;
}
private:
pointer_type p;
}; // template <bool const_tag> struct NodeIterator
static constexpr bool mutable_tag = false;
static constexpr bool const_tag = true;
using iterator_type = NodeIterator<mutable_tag>;
using const_iterator_type = NodeIterator<const_tag>;
public:
LinkedList() : head(nullptr) {}
iterator_type begin() const { return iterator_type(head); }
const iterator_type& end() const { return iterator_type::end; }
const_iterator_type cbegin() const { return const_iterator_type(head); }
const const_iterator_type& cend() const { return const_iterator_type::end; }
// [...]
}; // class LinkedList
// [...]
template<bool is_const>
const LinkedList::NodeIterator<is_const>
LinkedList::NodeIterator<is_const>::end(nullptr);
// [...]
现在,在合并函数代码中,您将迭代器定位在相应列表的头部
auto it_one = listOne.begin();
auto it_two = listTwo.cbegin();
递增it_one
直到它指向要插入副本的目标列表的元素,递增it_two
直到它指向将要复制的源列表的节点,然后
ListNode& one = *it_one;
ListNode* ptwo = new ListNode(*it_two); // copies
ptwo->next = one.next;
one.next = ptwo;
本质上就是这样。
因此,这里真正的问题不是技术上如何合并,而是操作的复杂性。
只要这两个列表都按照要创建的结果列表的预期顺序进行排序,就可以重用迭代器,从而简单地遍历这两个清单,它就是O(N)
和N = max(size(listOne), size(listTwo))
。
如果你必须对它们进行初步排序以保持合并本身的便宜,那么这种排序会导致O(N log N)
的复杂性。
顺便说一句,存储迭代器也简化了其他操作的实现;例如,显示它们只是
for (const auto& node : ListOne) {
std::cout << node.firstName << std::endl;
std::cout << node.lastName << std::endl;
std::cout << node.phoneNumber << std::endl;
}
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 使用CMake创建QML插件
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 试图在visual studio上用C++创建一个桌面应用程序
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 如何在C++20中创建模板别名的推导指南
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 如何创建一个空的全局类并在启动时实例化它
- 无法创建抽象类的实例
- 创建LinkedList退出,返回代码为-11(SIGSEGV)
- c++创建新的LinkedList类:Clear()方法指针被释放未分配
- 创建一个接受linkedlist作为输入的合并排序
- C++错误,显示创建链接列表调用"error LinkedList Interface is an inaccessable base of linkedlist"
- 合并两个LinkedList而不创建新的LinkedList
- C++没有默认构造函数?正在尝试为LinkedList创建Insert方法