📌  相关文章
📜  用于将元素的所有出现移动到链表中结束的 C++ 程序

📅  最后修改于: 2022-05-13 01:56:07.308000             🧑  作者: Mango

用于将元素的所有出现移动到链表中结束的 C++ 程序

给定一个链表和其中的一个键,任务是将所有出现的给定键移动到链表的末尾,保持所有其他元素的顺序相同。

例子:

Input  : 1 -> 2 -> 2 -> 4 -> 3
         key = 2 
Output : 1 -> 4 -> 3 -> 2 -> 2

Input  : 6 -> 6 -> 7 -> 6 -> 3 -> 10
         key = 6
Output : 7 -> 3 -> 10 -> 6 -> 6 -> 6

一个简单的解决方案是在链表中逐一查找给定键的所有出现。对于每个找到的事件,将其插入到末尾。我们这样做直到给定键的所有出现都移到最后。

时间复杂度: O(n 2 )

有效的解决方案1:是保留两个指针:
pCrawl => 一个一个遍历整个列表的指针。
pKey => 如果找到键,则指向该键的出现。其他与 pCrawl 相同。
我们从链表的头部开始上述两个指针。只有当pKey不指向某个键时,我们才移动pKey 。我们总是移动pCrawl 。所以,当pCrawlpKey不相同时,我们肯定已经找到了一个位于pCrawl之前的 key,所以我们在pCrawlpKey之间交换,并将pKey移动到下一个位置。循环不变量是,在交换数据之后,从pKeypCrawl的所有元素都是键。

下面是这种方法的实现。

C++
// C++ program to move all occurrences of a
// given key to end.
#include 
  
// A Linked list Node
struct Node {
    int data;
    struct Node* next;
};
  
// A utility function to create a new node.
struct Node* newNode(int x)
{
    Node* temp = new Node;
    temp->data = x;
    temp->next = NULL;
}
  
// Utility function to print the elements
// in Linked list
void printList(Node* head)
{
    struct Node* temp = head;
    while (temp != NULL) {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("
");
}
  
// Moves all occurrences of given key to
// end of linked list.
void moveToEnd(Node* head, int key)
{
    // Keeps track of locations where key
    // is present.
    struct Node* pKey = head;
  
    // Traverse list
    struct Node* pCrawl = head;
    while (pCrawl != NULL) {
        // If current pointer is not same as pointer
        // to a key location, then we must have found
        // a key in linked list. We swap data of pCrawl
        // and pKey and move pKey to next position.
        if (pCrawl != pKey && pCrawl->data != key) {
            pKey->data = pCrawl->data;
            pCrawl->data = key;
            pKey = pKey->next;
        }
  
        // Find next position where key is present
        if (pKey->data != key)
            pKey = pKey->next;
  
        // Moving to next Node
        pCrawl = pCrawl->next;
    }
}
  
// Driver code
int main()
{
    Node* head = newNode(10);
    head->next = newNode(20);
    head->next->next = newNode(10);
    head->next->next->next = newNode(30);
    head->next->next->next->next = newNode(40);
    head->next->next->next->next->next = newNode(10);
    head->next->next->next->next->next->next = newNode(60);
  
    printf("Before moveToEnd(), the Linked list is
");
    printList(head);
  
    int key = 10;
    moveToEnd(head, key);
  
    printf("
After moveToEnd(), the Linked list is
");
    printList(head);
  
    return 0;
}


C++
// C++ code to remove key element to end of linked list
#include
using namespace std;
  
// A Linked list Node
struct Node 
{
    int data;
    struct Node* next;
};
  
// A utility function to create a new node.
struct Node* newNode(int x)
{
    Node* temp = new Node;
    temp->data = x;
    temp->next = NULL;
}
  
// Function to remove key to end
Node *keyToEnd(Node* head, int key)
{
  
    // Node to keep pointing to tail
    Node* tail = head;
    if (head == NULL) 
    {
        return NULL;
    }
    while (tail->next != NULL) 
    {
        tail = tail->next;
    }
      
    // Node to point to last of linked list
    Node* last = tail;
    Node* current = head;
    Node* prev = NULL;
      
    // Node prev2 to point to previous when head.data!=key
    Node* prev2 = NULL;
      
    // loop to perform operations to remove key to end
    while (current != tail) 
    {
        if (current->data == key && prev2 == NULL) 
        {
            prev = current;
            current = current->next;
            head = current;
            last->next = prev;
            last = last->next;
            last->next = NULL;
            prev = NULL;
        }
        else
        {
            if (current->data == key && prev2 != NULL)
            {
                prev = current;
                current = current->next;
                prev2->next = current;
                last->next = prev;
                last = last->next;
                last->next = NULL;
            }
            else if (current != tail) 
            {
                prev2 = current;
                current = current->next;
            }
        }
    }
    return head;
}
  
// Function to display linked list
void printList(Node* head) 
{
    struct Node* temp = head;
    while (temp != NULL) 
    {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
  
  
// Driver Code
int main()
{
    Node* root = newNode(5);
    root->next = newNode(2);
    root->next->next = newNode(2);
    root->next->next->next = newNode(7);
    root->next->next->next->next = newNode(2);
    root->next->next->next->next->next = newNode(2);
    root->next->next->next->next->next->next = newNode(2);
  
    int key = 2;
    cout << "Linked List before operations :";
    printList(root);
    cout << "\nLinked List after operations :";
    root = keyToEnd(root, key);
    printList(root);
    return 0;
}
  
// This code is contributed by Rajout-Ji


输出:

Before moveToEnd(), the Linked list is
10 20 10 30 40 10 60 

After moveToEnd(), the Linked list is
20 30 40 60 10 10 10

时间复杂度: O(n) 只需要遍历一次列表。

高效解决方案 2:
1. 遍历链表,在尾部取一个指针。
2. 现在,检查密钥和节点->数据。如果它们相等,则将节点移动到 last-next,否则继续前进。

C++

// C++ code to remove key element to end of linked list
#include
using namespace std;
  
// A Linked list Node
struct Node 
{
    int data;
    struct Node* next;
};
  
// A utility function to create a new node.
struct Node* newNode(int x)
{
    Node* temp = new Node;
    temp->data = x;
    temp->next = NULL;
}
  
// Function to remove key to end
Node *keyToEnd(Node* head, int key)
{
  
    // Node to keep pointing to tail
    Node* tail = head;
    if (head == NULL) 
    {
        return NULL;
    }
    while (tail->next != NULL) 
    {
        tail = tail->next;
    }
      
    // Node to point to last of linked list
    Node* last = tail;
    Node* current = head;
    Node* prev = NULL;
      
    // Node prev2 to point to previous when head.data!=key
    Node* prev2 = NULL;
      
    // loop to perform operations to remove key to end
    while (current != tail) 
    {
        if (current->data == key && prev2 == NULL) 
        {
            prev = current;
            current = current->next;
            head = current;
            last->next = prev;
            last = last->next;
            last->next = NULL;
            prev = NULL;
        }
        else
        {
            if (current->data == key && prev2 != NULL)
            {
                prev = current;
                current = current->next;
                prev2->next = current;
                last->next = prev;
                last = last->next;
                last->next = NULL;
            }
            else if (current != tail) 
            {
                prev2 = current;
                current = current->next;
            }
        }
    }
    return head;
}
  
// Function to display linked list
void printList(Node* head) 
{
    struct Node* temp = head;
    while (temp != NULL) 
    {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
  
  
// Driver Code
int main()
{
    Node* root = newNode(5);
    root->next = newNode(2);
    root->next->next = newNode(2);
    root->next->next->next = newNode(7);
    root->next->next->next->next = newNode(2);
    root->next->next->next->next->next = newNode(2);
    root->next->next->next->next->next->next = newNode(2);
  
    int key = 2;
    cout << "Linked List before operations :";
    printList(root);
    cout << "\nLinked List after operations :";
    root = keyToEnd(root, key);
    printList(root);
    return 0;
}
  
// This code is contributed by Rajout-Ji

输出:

Linked List before operations :
5 2 2 7 2 2 2 
Linked List after operations :
5 7 2 2 2 2 2

感谢Ravinder Kumar提出这种方法。

高效的解决方案3:是维护一个单独的键列表。我们将此键列表初始化为空。我们遍历给定的列表。对于找到的每个键,我们将其从原始列表中删除并将其插入到单独的键列表中。我们最终将键列表链接到剩余给定列表的末尾。该解决方案的时间复杂度也是 O(n),而且它也只需要遍历一次列表。

有关详细信息,请参阅有关将所有出现的元素移动到链接列表中的完整文章!