【问题标题】:Splitting a single linked list in half将单个链表分成两半
【发布时间】:2018-02-03 23:45:21
【问题描述】:

我在分配数据结构时遇到了一些问题,非常感谢一些帮助。我正在从输入文件创建一个链接列表,该文件包含偶数个名字。我应该做五个功能; readFile、splitMerge、合并和遍历。我已经完成了 readFile 但我不知道如何拆分列表。

SplitMerge函数:创建一个split函数,将新创建的链表分成两个相等的子链表:myList1和myList2。例如,最初您将指向 (John, Jack, Jill, Jim)。拆分后,myList1 将指向 john 和 jack,而 myList2 将指向 jill 和 Jim。

到目前为止我的代码

#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

struct Node {
    string data;
    Node *next;
};

typedef Node *NodePtr;

NodePtr &readFile(NodePtr &, string); //function inputs the list

    void printList(NodePtr &); // function to print it out
    void splitMerge(NodePtr &, NodePtr &, string);
    void merge(); //ignore this
    void traverse(); //ignore this

int main() {
    ifstream fileIn("input.txt");

    string data;
    NodePtr head = NULL;
    NodePtr list2 = new Node();

        while (fileIn >> data)
        {
        readFile(head, data);   
        }
        cout << "Singly linked list: " << endl;
            printList(head);    
            cout << endl;

        splitMerge(head, list2, data);
        cout << "Split list: " << endl;
            printList(list2);

    fileIn.close();
return 0;
}

NodePtr &readFile(NodePtr &head,string data)
{
    NodePtr Alpha = new Node(); //new node called "Alpha
    Alpha->data = data; //assign alpha data to passed in "data"
    Alpha->next = NULL;
    NodePtr p = head; //head node

        if (p == NULL) head = Alpha; //if p is null, head is assigned alpha.
        else
        {
            while (p->next != NULL) p = p->next; //Fill nodes
            p->next = Alpha;
        }
    return head;
}

void printList(NodePtr &head)
{
    NodePtr p = head;

        while (p != NULL) //step through nodes till reaches NULL (end).
        {
            cout << p->data;
            p = p->next;
            cout << endl;
        }
}

void splitMerge(NodePtr &head, NodePtr &list2, string data)
{
    //NodePtr p = head;
    NodePtr slow = head;
    NodePtr fast = head;
    //list2->next = NULL;


    if (head != NULL)
    {
        while (fast != NULL && fast->next != NULL)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        list2->data = slow->data;
    }

    //while (list2->next != NULL) list2 = list2->next; //Fill nodes
    //list2->next = list2;
}

文本文件中的名称:

Sean
Megan
John
Alex
Ginger
Sam
Sarah
Jack

编辑:好的,所以我想我明白了。它现在编译、运行并正确地将列表一分为二。我现在唯一遇到的问题是我的第二个列表中只有一个名字,Ginger。如何在 list2 中包含节点 4-8?这里有点迷失了。

【问题讨论】:

  • 我没有看到你的尝试。
  • 好吧,我真的不知道从哪里开始,我在过去 6 个小时左右的时间里都在研究你在那里看到的东西。我能找到的关于拆分链表的所有信息都是关于循环列表或双重列表的。
  • 我明白,但这里没有人会为你做这项工作。在编程时,你不能期望通过寻找答案来找到问题的解决方案。您必须考虑它们,将它们分解为更小的问题,解决每个部分,将这些部分放在一起,然后在不起作用时进行调试。尝试更具体地说明您不了解的内容。
  • 循环遍历原始列表的元素。将中间元素的next 指针存储为指向列表2 的第一个元素的指针。将中间元素的next 指针设置为nullptr 以进行拆分。就是这样。
  • @zett42 好的,这就是我的开始。带有计数器的 for 循环,当达到 null 时停止。我如何获得中点,count/2 = midpoint?

标签: c++ merge split linked-list traversal


【解决方案1】:

在 cmets 中记录的修复。我没有使用 stdafx.h,因为我使用的是“emtpy”项目。我将 mergesplit() 更改为仅使用两个参数。

#include <fstream>
#include <iostream>
#include <string>
using namespace std;

struct Node {
    string data;
    Node *next;
};

typedef Node *NodePtr;

NodePtr &readFile(NodePtr &, string); //function inputs the list
void printList(NodePtr &); // function to print it out
void splitMerge(NodePtr &, NodePtr &);          // fix
void merge(); //ignore this
void traverse(); //ignore this

int main() {
    ifstream fileIn("input.txt");

    string data;
    NodePtr head = NULL;
    NodePtr list2 = NULL;                       // fix

    while (fileIn >> data)
        readFile(head, data);                   // simplify
    cout << "Singly linked list: " << endl;
    printList(head);    
    cout << endl;

    splitMerge(head, list2);
    cout << "First list:" << endl;              // show both lists
    printList(head);
    cout << endl;
    cout << "Second list:" << endl;
    printList(list2);

    fileIn.close();
    return 0;
}

NodePtr &readFile(NodePtr &head,string data)
{
    NodePtr Alpha = new Node(); //new node called "Alpha
    Alpha->data = data; //assign alpha data to passed in "data"
    Alpha->next = NULL;
    NodePtr p = head; //head node

        if (p == NULL) head = Alpha; //if p is null, head is assigned alpha.
        else
        {
            while (p->next != NULL) p = p->next; //Fill nodes
            p->next = Alpha;
        }
    return head;
}

void printList(NodePtr &head)
{
    NodePtr p = head;

        while (p != NULL) //step through nodes till reaches NULL (end).
        {
            cout << p->data;
            p = p->next;
            cout << endl;
        }
}

void splitMerge(NodePtr &head, NodePtr &list2)  // fix
{
    NodePtr slow = head;
    NodePtr fast = head;
    if(head == NULL || head->next == NULL)      // simplify
        return;                                 // simplify

    while (fast->next->next != NULL)            // fix
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    list2 = slow->next;                         // fix
    slow->next = NULL;                          // fix
}

虽然超出了类分配,但对于大型列表,列表的自下而上合并排序会更快。 Wiki有一个伪代码示例:

https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation_using_lists

再一次,将列表复制到数组中,删除列表,对数组进行排序(std::sort 或 std::stable_sort 可以),然后将数组复制到新列表,删除数组会更快.如果节点足够大,创建一个指向节点的指针数组,并对指针数组进行排序,然后从指针创建一个新列表,可能会更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 2013-05-25
    • 2013-12-06
    • 2012-05-26
    相关资源
    最近更新 更多