C++程序 给定一个单向链表的交替拆分-1

C++程序 给定一个单向链表的交替拆分-1

编写一个名为AlternatingSplit()的函数,它接收一个列表,并将其节点分成两个更小的列表’a’和’b’。子列表应该由原始列表中的交替元素组成。因此,如果原始列表是0->1->0->1->0->1,则一个子列表应该是0-> 0->0,另一个子列表应该是1->1->1。

方法1(简单):

最简单的方法是遍历源列表,并从源列表中获取节点,然后交替将它们放在’a’和’b’的前面(或开始)。唯一奇怪的部分是,节点将以在源列表中发生的相反顺序排列。方法2通过跟踪子列表中的最后一个节点,在末尾插入节点。

/* C++ Program to alternatively split
   a linked list into two halves */
#include <bits/stdc++.h>
using namespace std;
 
// Link list node
class Node
{
    public:
    int data;
    Node* next;
};
 
/* Pull off the front node of
   the source and put it in dest */
void MoveNode(Node** destRef,
              Node** sourceRef) ;
 
/* Given the source list, split its nodes
   into two shorter lists. If we number the
   elements 0, 1, 2, ... then all the even
   elements should go in the first list, and
   all the odd elements in the second. The
   elements in the new lists may be in any order. */
void AlternatingSplit(Node* source,
                      Node** aRef,
                      Node** bRef)
{
    /* Split the nodes of source
       to these 'a' and 'b' lists */
    Node* a = NULL;
    Node* b = NULL;
         
    Node* current = source;
    while (current != NULL)
    {
        // Move a node to list 'a'
        MoveNode(&a, &t);
        if (current != NULL)
        {
            // Move a node to list 'b'
            MoveNode(&b, &t);
        }
    }
    *aRef = a;
    *bRef = b;
}
 
/* Take the node from the front of
   the source, and move it to the front
   of the dest. It is an error to call
   this with the source list empty.    
   Before calling MoveNode():
   source == {1, 2, 3}
   dest == {1, 2, 3}
   After calling MoveNode():
   source == {2, 3}    
   dest == {1, 1, 2, 3} */
void MoveNode(Node** destRef,
              Node** sourceRef)
{
    // The front source node
    Node* newNode = *sourceRef;
    assert(newNode != NULL);
         
    // Advance the source pointer
    *sourceRef = newNode->next;
         
    // Link the old dest off the
    // new node
    newNode->next = *destRef;
         
    // Move dest to point to the
    // new node
    *destRef = newNode;
}
 
// Utility Functions
/* Function to insert a node at
   the beginning of the linked list */
void push(Node** head_ref,
          int new_data)
{
    // Allocate node
    Node* new_node = new Node();
     
    // Put in the data
    new_node->data = new_data;
     
    // Link the old list of the
    // new node
    new_node->next = (*head_ref);    
     
    // Move the head to point to the
    // new node
    (*head_ref) = new_node;
}
 
/* Function to print nodes
   in a given linked list */
void printList(Node *node)
{
    while(node != NULL)
    {
    cout << node->data << " ";
    node = node->next;
    }
}
 
// Driver code
int main()
{
    // Start with the empty list
    Node* head = NULL;
    Node* a = NULL;
    Node* b = NULL;
     
    /* Let us create a sorted linked list
       to test the functions
       Created linked list will be
       0->1->2->3->4->5 */
    push(&head, 5);
    push(&head, 4);
    push(&head, 3);
    push(&head, 2);
    push(&head, 1);                                
    push(&head, 0);
     
    cout << "Original linked List: ";
    printList(head);
     
    // Remove duplicates from linked list
    AlternatingSplit(head, &a, &b);
     
    cout << "Resultant Linked List 'a' : ";
    printList(a);        
     
    cout << "Resultant Linked List 'b' : ";
    printList(b);        
     
    return 0;
}
// This code is contributed by rathbhupendra```  

输出:

原始链表: 0 1 2 3 4 5 
结果链表 'a' : 4 2 0 
结果链表 'b' : 5 3 1

时间复杂度:O(n), 其中n是给定链接列表中的节点数。

辅助空间:O(1)

方法2(使用虚拟节点):

这是一种替代方法,该方法按照与源列表相同的顺序构建子列表。代码在构建“a”和“b”列表时使用临时虚拟头节点。每个子列表都有一个“tail”指针,指向其当前的最后一个节点 – 这样可以轻松地将新节点附加到每个列表的末尾。虚拟节点最初为尾指针提供了一些指向的对象。在这种情况下,虚拟节点效率很高,因为它们是临时分配的,分配在堆栈中。也可以使用本地的“引用指针”(它们始终指向列表中的最后一个指针而不是最后一个节点),以避免使用虚拟节点。

void AlternatingSplit(Node* source,
                      Node** aRef,
                      Node** bRef)
{
    Node aDummy;
     
    // 指向'a'中的最后一个节点
    Node* aTail = &aDummy
    Node bDummy;
     
    // 指向'b'中的最后一个节点
    Node* bTail = &bDummy
    Node* current = source;
    aDummy.next = NULL;
    bDummy.next = NULL;
    while (current != NULL)
    {
        // 添加到'a'中的末尾
        MoveNode(&(aTail->next), &t);
  
        // 推进'a'的末尾
        aTail = aTail->next;
        if (current != NULL)
        {
            MoveNode(&(bTail->next), ¤t);
            bTail = bTail->next;
        }
    }
    *aRef = aDummy.next;
    *bRef = bDummy.next;
}
// 此代码由rathbhupendra提供```  

时间复杂度: O(n),其中n是给定链表中的节点数。

空间复杂度: O(n),因为该函数创建了2个新的链表。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程