Get the best out of our app
GeeksforGeeks App
Open App
Browser
Continue

# Implement Undo and Redo features of a Text Editor

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 ABC
Explanation:
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:

Below is the implementation of the above approach:

## C++

 `// C++ Program to implement``// the above approach``#include ``using` `namespace` `std;` `// Function to perform``// "WRITE X" operation``void` `WRITE(stack<``char``>& Undo,``           ``char` `X)``{``    ``// Push an element to``    ``// the top of stack``    ``Undo.push(X);``}` `// Function to perform``// "UNDO" operation``void` `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" operation``void` `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" operation``void` `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 document``void` `QUERY(vector 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 Code``int` `main()``{` `    ``vector Q = { ``"WRITE A"``, ``"WRITE B"``,``                         ``"WRITE C"``, ``"UNDO"``,``                         ``"READ"``, ``"REDO"``, ``"READ"` `};``    ``QUERY(Q);``    ``return` `0;``}`

## Java

 `// Java Program to implement the above approach``import` `java.util.*;``public` `class` `Main``{``    ``// 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.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.`

## Python3

 `# Python Program to implement``# the above approach``global` `Undo``global` `Redo` `# Stores the history of all``# the queries that have been``# processed on the document``Undo ``=` `[]` `# Stores the elements``# of REDO query``Redo ``=` `[]` `# Function to perform``# "WRITE X" operation``def` `WRITE(Undo, X):` `    ``# Push an element to``    ``# the top of stack``    ``Undo.append(X)` `# Function to perform``# "UNDO" operation``def` `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" operation``def` `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" operation``def` `READ(Undo):``    ``print``(``*``Undo, sep ``=` `"",``          ``end ``=` `" "``)` `# Function to perform the``# queries on the document``def` `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 Code``Q ``=` `[``"WRITE A"``, ``"WRITE B"``, ``"WRITE C"``,``     ``"UNDO"``, ``"READ"``, ``"REDO"``, ``"READ"``]``QUERY(Q)` `#This code is contributed by avanitrachhadiya2155`

## C#

 `// C# Program to implement the above approach``using` `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`

## Javascript

 ``

Output:

`AB ABC`

Time Complexity:
UNDO: O(1)
REDO: O(1)
WRITE: O(1)
READ: (N), where N denotes the size of the Undo stack
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up