Implement Undo and Redo features of a Text Editor - GeeksforGeeks

27 Aug, 2021
Given an array of strings Q[], consisting of queries of the following types:
“WRITE X”: Write a character X into the document.
“UNDO”: Erases the last change made to the document.
“REDO”: Restores the most recent UNDO operation performed on the document.
“READ”: Reads and prints the contents of the documents.
Examples:
Input: Q = {“WRITE A”, “WRITE B”, “WRITE C”, “UNDO”, “READ”, “REDO”, “READ”}Output: AB ABCExplanation: Perform “WRITE A” on the document. Therefore, the document contains only “A”.Perform “WRITE B” on the document. Therefore, the document contains “AB”.Perform “WRITE C” on the document. Therefore, the document contains “ABC”.Perform “UNDO” on the document. Therefore, the document contains “AB”.Print the contents of the document, i.e. “AB”Perform “REDO” on the document. Therefore, the document contains “ABC”.Print the contents of the document, i.e. “ABC”
Input: Q = {“WRITE x”, “WRITE y”, “UNDO”, “WRITE z”, “READ”, “REDO”, “READ”}Output:xz xzy
Approach: The problem can be solved using Stack. Follow the steps below to solve the problem:
Initialize two stacks, say Undo and Redo.
Traverse the array of strings, Q, and perform the following operations:
If “WRITE” string is encountered, push the character to Undo stack
If “UNDO” string is encountered, pop the top element from Undo stack and push it to Redo stack.
If “REDO” string is encountered, pop the top element of Redo stack and push it into the Undo stack.
If “READ” string is encountered, print all the elements of the Undo stack in reverse order.
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ Program to implement// the above approach#include <bits/stdc++.h>using namespace std; // Function to perform// "WRITE X" operationvoid WRITE(stack<char>& Undo,           char X){    // Push an element to    // the top of stack    Undo.push(X);} // Function to perform// "UNDO" operationvoid UNDO(stack<char>& Undo,          stack<char>& Redo){    // Stores top element    // of the stack    char X = Undo.top();     // Erase top element    // of the stack    Undo.pop();     // Push an element to    // the top of stack    Redo.push(X);} // Function to perform// "REDO" operationvoid REDO(stack<char>& Undo,          stack<char>& Redo){    // Stores the top element    // of the stack    char X = Redo.top();     // Erase the top element    // of the stack    Redo.pop();     // Push an element to    // the top of the stack    Undo.push(X);} // Function to perform// "READ" operationvoid READ(stack<char> Undo){    // Store elements of stack    // in reverse order    stack<char> revOrder;     // Traverse Undo stack    while (!Undo.empty()) {        // Push an element to        // the top of stack        revOrder.push(Undo.top());         // Erase top element        // of stack        Undo.pop();    }     while (!revOrder.empty()) {        // Print the top element        // of the stack        cout << revOrder.top();      Undo.push(revOrder.top());         // Erase the top element        // of the stack        revOrder.pop();    }     cout << " ";} // Function to perform the// queries on the documentvoid QUERY(vector<string> Q){    // Stores the history of all    // the queries that have been    // processed on the document    stack<char> Undo;     // Stores the elements    // of REDO query    stack<char> Redo;     // Stores total count    // of queries    int N = Q.size();     // Traverse all the query    for (int i = 0; i < N; i++) {        if (Q[i] == "UNDO") {            UNDO(Undo, Redo);        }        else if (Q[i] == "REDO") {            REDO(Undo, Redo);        }        else if (Q[i] == "READ") {            READ(Undo);        }        else {            WRITE(Undo, Q[i][6]);        }    }} // Driver Codeint main(){     vector<string> Q = { "WRITE A", "WRITE B",                         "WRITE C", "UNDO",                         "READ", "REDO", "READ" };    QUERY(Q);    return 0;}
// Java Program to implement the above approachimport java.util.*;public class Main{    // Stores the history of all    // the queries that have been    // processed on the document    static Stack<Character> Undo = new Stack<Character>();      // Stores the elements    // of REDO query    static Stack<Character> Redo = new Stack<Character>();         // Function to perform    // "WRITE X" operation    static void WRITE(Stack<Character> Undo, char X)    {              // Push an element to        // the top of stack        Undo.push(X);    }      // Function to perform    // "UNDO" operation    static void UNDO(Stack<Character> Undo, Stack<Character> Redo)    {              // Stores top element        // of the stack        char X = (char)Undo.peek();          // Erase top element        // of the stack        Undo.pop();          // Push an element to        // the top of stack        Redo.push(X);    }      // Function to perform    // "REDO" operation    static void REDO(Stack<Character> Undo, Stack<Character> Redo)    {              // Stores the top element        // of the stack        char X = (char)Redo.peek();          // Erase the top element        // of the stack        Redo.pop();          // Push an element to        // the top of the stack        Undo.push(X);    }      // Function to perform    // "READ" operation    static void READ(Stack<Character> Undo)    {              // Store elements of stack        // in reverse order        Stack<Character> revOrder = new Stack<Character>();          // Traverse Undo stack        while (Undo.size() > 0)        {                      // Push an element to            // the top of stack            revOrder.push(Undo.peek());              // Erase top element            // of stack            Undo.pop();        }          while (revOrder.size() > 0)        {                      // Print the top element            // of the stack            System.out.print(revOrder.peek());              Undo.push(revOrder.peek());              // Erase the top element            // of the stack            revOrder.pop();        }          System.out.print(" ");    }      // Function to perform the    // queries on the document    static void QUERY(String[] Q)    {        // Stores total count        // of queries        int N = Q.length;          // Traverse all the query        for (int i = 0; i < N; i++)        {            if(Q[i] == "UNDO")            {                UNDO(Undo, Redo);            }            else if(Q[i] == "REDO")            {                REDO(Undo, Redo);            }            else if(Q[i] == "READ")            {                READ(Undo);            }            else            {                WRITE(Undo, Q[i].charAt(6));            }        }    }         public static void main(String[] args) {        String[] Q = { "WRITE A", "WRITE B", "WRITE C", "UNDO", "READ", "REDO", "READ" };        QUERY(Q);    }} // This code is contributed by divyeshrabadiya07.
# Python Program to implement# the above approachglobal Undoglobal Redo # Stores the history of all# the queries that have been# processed on the documentUndo = [] # Stores the elements# of REDO queryRedo = [] # Function to perform# "WRITE X" operationdef WRITE(Undo, X):     # Push an element to    # the top of stack    Undo.append(X) # Function to perform# "UNDO" operationdef UNDO(Undo, Redo):     # Stores top element    # of the stack    X = Undo[-1]     # Erase top element    # of the stack    Undo.pop()     # Push an element to    # the top of stack    Redo.append(X) # Function to perform# "REDO" operationdef REDO(Undo, Redo):     # Stores the top element    # of the stack    X = Redo[-1]     # Erase the top element    # of the stack    Redo.pop()     # Push an element to    # the top of the stack    Undo.append(X) # Function to perform# "READ" operationdef READ(Undo):    print(*Undo, sep = "",          end = " ") # Function to perform the# queries on the documentdef QUERY(Q):     # Stores total count    # of queries    N = len(Q)     # Traverse all the query    for i in range(N):        if(Q[i] == "UNDO"):            UNDO(Undo, Redo)        elif(Q[i] == "REDO"):            REDO(Undo, Redo)        elif(Q[i] == "READ"):            READ(Undo)        else:            WRITE(Undo, Q[i][6]) # Driver CodeQ = ["WRITE A", "WRITE B", "WRITE C",     "UNDO", "READ", "REDO", "READ"]QUERY(Q) #This code is contributed by avanitrachhadiya2155
// C# Program to implement the above approachusing System;using System.Collections;class GFG {         // Stores the history of all    // the queries that have been    // processed on the document    static Stack Undo = new Stack();      // Stores the elements    // of REDO query    static Stack Redo = new Stack();         // Function to perform    // "WRITE X" operation    static void WRITE(Stack Undo, char X)    {              // Push an element to        // the top of stack        Undo.Push(X);    }      // Function to perform    // "UNDO" operation    static void UNDO(Stack Undo, Stack Redo)    {              // Stores top element        // of the stack        char X = (char)Undo.Peek();          // Erase top element        // of the stack        Undo.Pop();          // Push an element to        // the top of stack        Redo.Push(X);    }      // Function to perform    // "REDO" operation    static void REDO(Stack Undo, Stack Redo)    {              // Stores the top element        // of the stack        char X = (char)Redo.Peek();          // Erase the top element        // of the stack        Redo.Pop();          // Push an element to        // the top of the stack        Undo.Push(X);    }      // Function to perform    // "READ" operation    static void READ(Stack Undo)    {              // Store elements of stack        // in reverse order        Stack revOrder = new Stack();          // Traverse Undo stack        while (Undo.Count > 0)        {                      // Push an element to            // the top of stack            revOrder.Push(Undo.Peek());              // Erase top element            // of stack            Undo.Pop();        }          while (revOrder.Count > 0)        {                      // Print the top element            // of the stack            Console.Write(revOrder.Peek());              Undo.Push(revOrder.Peek());              // Erase the top element            // of the stack            revOrder.Pop();        }          Console.Write(" ");    }      // Function to perform the    // queries on the document    static void QUERY(string[] Q)    {        // Stores total count        // of queries        int N = Q.Length;          // Traverse all the query        for (int i = 0; i < N; i++)        {            if(Q[i] == "UNDO")            {                UNDO(Undo, Redo);            }            else if(Q[i] == "REDO")            {                REDO(Undo, Redo);            }            else if(Q[i] == "READ")            {                READ(Undo);            }            else            {                WRITE(Undo, Q[i][6]);            }        }    }       static void Main() {    string[] Q = { "WRITE A", "WRITE B", "WRITE C", "UNDO", "READ", "REDO", "READ" };    QUERY(Q);  }} // This code is contributed by rameshtravel07
<script>    // Javascript Program to implement the above approach         // Stores the history of all    // the queries that have been    // processed on the document    let Undo = [];     // Stores the elements    // of REDO query    let Redo = [];         // Function to perform    // "WRITE X" operation    function WRITE(Undo, X)    {             // Push an element to        // the top of stack        Undo.push(X)    }     // Function to perform    // "UNDO" operation    function UNDO(Undo, Redo)    {             // Stores top element        // of the stack        let X = Undo[Undo.length - 1];         // Erase top element        // of the stack        Undo.pop();         // Push an element to        // the top of stack        Redo.push(X);    }     // Function to perform    // "REDO" operation    function REDO(Undo, Redo)    {             // Stores the top element        // of the stack        let X = Redo[Redo.length - 1];         // Erase the top element        // of the stack        Redo.pop();         // Push an element to        // the top of the stack        Undo.push(X);    }     // Function to perform    // "READ" operation    function READ(Undo)    {             // Store elements of stack        // in reverse order        let revOrder = [];         // Traverse Undo stack        while (Undo.length > 0)        {                     // Push an element to            // the top of stack            revOrder.push(Undo[Undo.length - 1]);             // Erase top element            // of stack            Undo.pop();        }         while (revOrder.length > 0)        {                     // Print the top element            // of the stack            document.write(revOrder[revOrder.length - 1]);              Undo.push(revOrder[revOrder.length - 1]);             // Erase the top element            // of the stack            revOrder.pop();        }         document.write(" ");    }     // Function to perform the    // queries on the document    function QUERY(Q)    {        // Stores total count        // of queries        N = Q.length         // Traverse all the query        for (let i = 0; i < N; i++)        {            if(Q[i] == "UNDO")            {                UNDO(Undo, Redo);            }            else if(Q[i] == "REDO")            {                REDO(Undo, Redo);            }            else if(Q[i] == "READ")            {                READ(Undo);            }            else            {                WRITE(Undo, Q[i][6]);            }        }    }         let Q = [ "WRITE A", "WRITE B", "WRITE C", "UNDO", "READ", "REDO", "READ" ];    QUERY(Q); // This code is contributed by suresh07.</script>
AB ABC
 
Time Complexity:UNDO: O(1)REDO: O(1)WRITE: O(1)READ: (N), where N denotes the size of the Undo stackAuxiliary Space: O(N)
avanitrachhadiya2155
srivastavaharshit848
suresh07
rameshtravel07
divyeshrabadiya07
Amazon
Amazon-Question
cpp-stack
interview-preparation
Arrays
Data Structures
Stack
Strings
Amazon
Data Structures
Arrays
Strings
Stack
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Maximum and minimum of an array using minimum number of comparisons
Top 50 Array Coding Problems for Interviews
Stack Data Structure (Introduction and Program)
Introduction to Arrays
Multidimensional Arrays in Java
SDE SHEET - A Complete Guide for SDE Preparation
Top 50 Array Coding Problems for Interviews
DSA Sheet by Love Babbar
Doubly Linked List | Set 1 (Introduction and Insertion)
Introduction to Algorithms