Open In App

Gap Buffer Data Structure

Last Updated : 02 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

INTRODUCTION:

Gap Buffer is a data structure for the dynamic insertion and deletion of elements in a buffer or an array. It represents a buffer or an array as a gap surrounded by two pointers, one pointing to the beginning of the buffer and the other pointing to the end. When elements are inserted or deleted, the gap is moved to accommodate the change, instead of resizing the entire buffer.

Gap Buffer is designed to be an efficient data structure for real-time applications, such as text editors and code editors, where fast and dynamic insertion and deletion of elements are important. The gap buffer data structure provides an average time complexity of O(1) for inserting elements at the current cursor position, making it a suitable choice for applications that require low latency.

In addition to its efficiency and real-time capabilities, Gap Buffer is also a space-efficient data structure, as it uses a gap to represent empty space in the buffer, minimizing the number of memory reallocations required for insertions and deletions. The Gap Buffer data structure is relatively simple to implement, making it a popular choice for a wide range of applications.

Gap Buffer is a data structure used for editing and storing text in an efficient manner that is being currently edited. It is also similar to an array but a gap is introduced in the array for handling multiple changes at the cursor. Let’s assume a gap to be another array that contains empty spaces. 

Example: Consider an example with initial gap size 10, initially, array or gap are of the same size, as we insert the elements in the array similarly elements will be inserted in the gap buffer, the only difference is gap size reduces on each insert. 

 
 

This was the basic case to insert the character in the front. Now, whenever there is need to insert a character at certain position we will just move the gap up-to that position using left() and right() then try to insert the character.

Need for Gap Buffer

  • Array is a data structure which stores items at contiguous memory location. However, it takes O(1) insertion at end of the array while O(n) time in front because the array will be shifted n places right, n being the length of the array.
  • When it comes to text editors we need a faster data structure for insertion, modification as there are multiple changes at the cursor positions.
  • In worst case array will take O(n) time for insertion or modification as shown in the example below.
  • For inserting ‘GEEKS’ at the front, space is made for inserting each character by shifting the array. 

Basic operations in Gap Buffer

  • insert(): It is a procedure used to insert character into the text at a given position. It first checks whether the gap is empty or not, if it finds that the gap is empty it calls procedure grow() and resizes the gap and now the element can be inserted.
  • left() : It is a procedure used for moving the cursor to left and this cursor point is used as position for changes. 
     

  • right: It is a procedure used for moving the cursor to right and this cursor point is used as position for changes. 
  • grow: It is a procedure used when the gap size has become zero and therefore we need to resize the array by inserting a gap at desired position. 

Gap Buffer vs Ropes

Now, although its insertion is taking O(1) time but there is another function grow() which  takes approximately O(n) time. So there might a thought that this may take the same time as the rope data structures but the cost of grow is being compensated by amortized cost of other cheaper procedures such as left(), right() and insert(). Therefore this data structure get preferences in text-editors over other such as rope as it is easy to implement.

Implementing Gap Buffer

C++




// C++ program of implementation of gap buffer
 
#include <bits/stdc++.h>
using namespace std;
 
char buffer[50];
int gap_size = 10;
int gap_left = 0;
int gap_right = gap_size - gap_left-1;
int size = 10;
 
// Function that is used to grow the gap
// at index position and return the array
 
 
void grow(int k, int position)
{
 
    char a[size];
 
    // Copy characters of buffer to a[]
    // after position
    for (int i = position; i < size; i++) {
        a[i - position] = buffer[i];
         
    }
     
    // Insert a gap of k from index position
    // gap is being represented by '-'
    for (int i = 0; i < k; i++) {
        buffer[i + position] = '_';
    }
     
    // Reinsert the remaining array
    for (int i = 0; i < position + k; i++) {
        buffer[position + k + i] = a[i];
    }
 
    size += k;
    gap_right+=k;
}
 
// Function that is used to move the gap
// left in the array
void left(int position)
{
    // Move the gap left character by character
    // and the buffers
    while (position < gap_left) {
        gap_left--;
        gap_right--;
        buffer[gap_right+1] = buffer[gap_left];
        buffer[gap_left]='_';
    }
}
 
// Function that is used to move the gap
// right in the array
void right(int position)
{
    // Move the gap right character by character
    // and the buffers
    while (position > gap_left) {
        gap_left++;
        gap_right++;
        buffer[gap_left-1] = buffer[gap_right];
        buffer[gap_right]='_';
    }
}
 
// Function to control the movement of gap
// by checking its position to the point of
// insertion
void move_cursor(int position)
{
    if (position < gap_left) {
        left(position);
    }
    else {
        right(position);
    }
}
 
// Function to insert the string to the buffer
// at point position
void insert(string input, int position)
{
    int len = input.length();
    int i = 0;
 
    // If the point is not the gap check
    // and move the cursor to that point
    if (position != gap_left) {
        move_cursor(position);
    }
 
    // Insert characters one by one
    while (i < len) {
        // If the gap is empty grow the size
        if (gap_right == gap_left) {
            int k = 10;
            grow(k, position);
        }
 
        // Insert the character in the gap and
        // move the gap
        buffer[gap_left] = input[i];
        gap_left++;
        i++;
        position++;
    }
}
 
// Driver code
int main()
{
    // Initializing the gap buffer with size 10
    for (int i = 0; i < 10; i++) {
        buffer[i] = '_';
    }
 
    cout << "Initializing the gap buffer "
         << "with size 10" << endl;
  
    for (int i = 0; i < size; i++) {
        cout << buffer[i]<<" ";
    }
 
    cout << endl;
 
    // Inserting a string to buffer
    string input = "GEEKSGEEKS";
    int position = 0;
 
    insert(input, position);
 
    cout << endl;
    cout << "Inserting a string to buffer"
         << ": GEEKSGEEKS" << endl;
    cout << "Output: ";
    for (int i = 0; i < size; i++) {
        cout << buffer[i]<<" ";
    }
 
    input = "FOR";
    position = 5;
 
    insert(input, position);
 
    cout << endl;
    cout << endl;
     
    cout << "Inserting a string to buffer"
         << ": FOR" << endl;
    cout << "Output: ";
    for (int i = 0; i < size; i++) {
        cout << buffer[i]<<" ";
    }
 
 
    return 0;
}


Java




// Java program of implementation of gap buffer
import java.util.*;
class GFG
{
static char []buffer = new char[50];
static int gap_size = 10;
static int gap_left = 0;
static int gap_right = gap_size - gap_left - 1;
static int size = 10;
 
// Function that is used to grow the gap
// at index position and return the array
static void grow(int k, int position)
{
    char []a = new char[size];
 
    // Copy characters of buffer to a[]
    // after position
    for (int i = position; i < size; i++)
    {
        a[i - position] = buffer[i];
    }
     
    // Insert a gap of k from index position
    // gap is being represented by '-'
    for (int i = 0; i < k; i++)
    {
        buffer[i + position] = '_';
    }
     
    // Reinsert the remaining array
    for (int i = 0; i < k; i++)
    {
        buffer[position + k + i] = a[i];
    }
 
    size += k;
    gap_right += k;
}
 
// Function that is used to move the gap
// left in the array
static void left(int position)
{
    // Move the gap left character by character
    // and the buffers
    while (position < gap_left)
    {
        gap_left--;
        gap_right--;
        buffer[gap_right + 1] = buffer[gap_left];
        buffer[gap_left]='_';
    }
}
 
// Function that is used to move the gap
// right in the array
static void right(int position)
{
     
    // Move the gap right character by character
    // and the buffers
    while (position > gap_left)
    {
        gap_left++;
        gap_right++;
        buffer[gap_left - 1] = buffer[gap_right];
        buffer[gap_right]='_';
    }
}
 
// Function to control the movement of gap
// by checking its position to the point of
// insertion
static void move_cursor(int position)
{
    if (position < gap_left)
    {
        left(position);
    }
    else
    {
        right(position);
    }
}
 
// Function to insert the string to the buffer
// at point position
static void insert(String input, int position)
{
    int len = input.length();
    int i = 0;
 
    // If the point is not the gap check
    // and move the cursor to that point
    if (position != gap_left)
    {
        move_cursor(position);
    }
 
    // Insert characters one by one
    while (i < len)
    {
        // If the gap is empty grow the size
        if (gap_right == gap_left)
        {
            int k = 10;
            grow(k, position);
        }
 
        // Insert the character in the gap and
        // move the gap
        buffer[gap_left] = input.charAt(i);
        gap_left++;
        i++;
        position++;
    }
}
 
// Driver code
public static void main(String[] args)
{
    // Initializing the gap buffer with size 10
    for (int i = 0; i < 10; i++)
    {
        buffer[i] = '_';
    }
 
    System.out.println("Initializing the gap" +
                       " buffer with size 10");
 
    for (int i = 0; i < size; i++)
    {
        System.out.print(buffer[i] + " ");
    }
 
    System.out.println();
 
    // Inserting a string to buffer
    String input = "GEEKSGEEKS";
    int position = 0;
 
    insert(input, position);
 
    System.out.println();
    System.out.println("Inserting a string " +
                       "to buffer: GEEKSGEEKS");
    System.out.print("Output: ");
    for (int i = 0; i < size; i++)
    {
        System.out.print(buffer[i] + " ");
    }
 
    input = "FOR";
    position = 5;
 
    insert(input, position);
 
    System.out.println();
    System.out.println();
     
    System.out.println("Inserting a string" +
                       " to buffer: FOR");
    System.out.print("Output: ");
    for (int i = 0; i < size; i++)
    {
        System.out.print(buffer[i] + " ");
    }
    }
}
 
// This code is contributed by Princi Singh


Python3




# Python program of implementation of gap buffer
 
buffer = ['_' for i in range(50)]
gap_size = 10
gap_left = 0
gap_right = gap_size - gap_left - 1
size = 10
 
# Function that is used to grow the gap
# at index position and return the array
def grow(k, position):
    global size, gap_right, gap_left, buffer
    a = buffer[position:size]
 
    # Insert a gap of k from index position
    # gap is being represented by '-'
    buffer[position:position+k] = ['_' for i in range(k)]
 
    # Reinsert the remaining array
    buffer[position+k:position+k+size-position] = a
 
    size += k
    gap_right += k
 
# Function that is used to move the gap
# left in the array
def left(position):
    global gap_left, gap_right, buffer
    # Move the gap left character by character
    # and the buffers
    while position < gap_left:
        gap_left -= 1
        gap_right -= 1
        buffer[gap_right+1] = buffer[gap_left]
        buffer[gap_left] = '_'
 
# Function that is used to move the gap
# right in the array
def right(position):
    global gap_left, gap_right, buffer
    # Move the gap right character by character
    # and the buffers
    while position > gap_left:
        gap_left += 1
        gap_right += 1
        buffer[gap_left-1] = buffer[gap_right]
        buffer[gap_right] = '_'
 
# Function to control the movement of gap
# by checking its position to the point of
# insertion
 
 
def move_cursor(position):
    if position < gap_left:
        left(position)
    else:
        right(position)
 
# Function to insert the string to the buffer
# at point position
 
 
def insert(input, position):
    global gap_left, gap_right
    len_input = len(input)
    i = 0
 
    # If the point is not the gap check
    # and move the cursor to that point
    if position != gap_left:
        move_cursor(position)
 
    # Insert characters one by one
    while i < len_input:
        # If the gap is empty grow the size
        if gap_right == gap_left:
            k = 10
            grow(k, position)
 
        # Insert the character in the gap and
        # move the gap
        buffer[gap_left] = input[i]
        gap_left += 1
        i += 1
        position += 1
 
 
# Initializing the gap buffer with size 10
for i in range(10):
    buffer[i] = '_'
 
print("Initializing the gap buffer with size 10")
print(buffer[:size])
 
# Inserting a string to buffer
input_str = "GEEKSGEEKS"
position = 0
 
insert(input_str, position)
 
print("Inserting a string to buffer: GEEKSGEEKS")
print("Output:", buffer[:size])
 
input_str = "FOR"
position = 5
 
insert(input_str, position)
 
print("\n")
print("\n")
 
print("Inserting a string to buffer: FOR")
print("Output: ", end="")
for i in range(size):
    print(buffer[i], end=" ")


C#




// C# program of implementation of gap buffer
using System;
     
class GFG
{
static char []buffer = new char[50];
static int gap_size = 10;
static int gap_left = 0;
static int gap_right = gap_size - gap_left - 1;
static int size = 10;
 
// Function that is used to grow the gap
// at index position and return the array
static void grow(int k, int position)
{
    char []a = new char[size];
 
    // Copy characters of buffer to a[]
    // after position
    for (int i = position; i < size; i++)
    {
        a[i - position] = buffer[i];
    }
     
    // Insert a gap of k from index position
    // gap is being represented by '-'
    for (int i = 0; i < k; i++)
    {
        buffer[i + position] = '_';
    }
     
    // Reinsert the remaining array
    for (int i = 0; i < k; i++)
    {
        buffer[position + k + i] = a[i];
    }
 
    size += k;
    gap_right += k;
}
 
// Function that is used to move the gap
// left in the array
static void left(int position)
{
    // Move the gap left character by character
    // and the buffers
    while (position < gap_left)
    {
        gap_left--;
        gap_right--;
        buffer[gap_right + 1] = buffer[gap_left];
        buffer[gap_left]='_';
    }
}
 
// Function that is used to move the gap
// right in the array
static void right(int position)
{
     
    // Move the gap right character by character
    // and the buffers
    while (position > gap_left)
    {
        gap_left++;
        gap_right++;
        buffer[gap_left - 1] = buffer[gap_right];
        buffer[gap_right] = '_';
    }
}
 
// Function to control the movement of gap
// by checking its position to the point of
// insertion
static void move_cursor(int position)
{
    if (position < gap_left)
    {
        left(position);
    }
    else
    {
        right(position);
    }
}
 
// Function to insert the string to the buffer
// at point position
static void insert(String input, int position)
{
    int len = input.Length;
    int i = 0;
 
    // If the point is not the gap check
    // and move the cursor to that point
    if (position != gap_left)
    {
        move_cursor(position);
    }
 
    // Insert characters one by one
    while (i < len)
    {
        // If the gap is empty grow the size
        if (gap_right == gap_left)
        {
            int k = 10;
            grow(k, position);
        }
 
        // Insert the character in the gap and
        // move the gap
        buffer[gap_left] = input[i];
        gap_left++;
        i++;
        position++;
    }
}
 
// Driver code
public static void Main(String[] args)
{
    // Initializing the gap buffer with size 10
    for (int i = 0; i < 10; i++)
    {
        buffer[i] = '_';
    }
 
    Console.WriteLine("Initializing the gap" +
                      " buffer with size 10");
 
    for (int i = 0; i < size; i++)
    {
        Console.Write(buffer[i] + " ");
    }
 
    Console.WriteLine();
 
    // Inserting a string to buffer
    String input = "GEEKSGEEKS";
    int position = 0;
 
    insert(input, position);
 
    Console.WriteLine();
    Console.WriteLine("Inserting a string " +
                    "to buffer: GEEKSGEEKS");
    Console.Write("Output: ");
    for (int i = 0; i < size; i++)
    {
        Console.Write(buffer[i] + " ");
    }
 
    input = "FOR";
    position = 5;
 
    insert(input, position);
 
    Console.WriteLine();
    Console.WriteLine();
     
    Console.WriteLine("Inserting a string" +
                         " to buffer: FOR");
    Console.Write("Output: ");
    for (int i = 0; i < size; i++)
    {
        Console.Write(buffer[i] + " ");
    }
    }
}
 
// This code is contributed by 29AjayKumar


Javascript




let buffer = new Array(50).fill('_');
let gap_size = 10;
let gap_left = 0;
let gap_right = gap_size - gap_left - 1;
let size = 10;
// Function that is used to grow the gap
// at index position and return the array
function grow(k, position) {
    let a = buffer.slice(position, size);
    // Copy characters of buffer to a[]
    // after position
    buffer.splice(position, size - position, ...('_'.repeat(k)));
    // Insert a gap of k from index position
    // gap is being represented by '-'
     // Reinsert the remaining array
    buffer.splice(position + k, 0, ...a);
    size += k;
    gap_right += k;
}
// Function that is used to move the gap
// left in the array
function left(position) {
        // Move the gap left character by character
    // and the buffers
    while (position < gap_left) {
        gap_left--;
        gap_right--;
        buffer[gap_right + 1] = buffer[gap_left];
        buffer[gap_left] = '_';
    }
}
// Function that is used to move the gap
// right in the array
function right(position) {
    // Move the gap right character by character
    // and the buffers
    while (position > gap_left) {
        gap_left++;
        gap_right++;
        buffer[gap_left - 1] = buffer[gap_right];
        buffer[gap_right] = '_';
    }
}
// Function to control the movement of gap
// by checking its position to the point of
// insertion
function move_cursor(position) {
    if (position < gap_left) {
        left(position);
    } else {
        right(position);
    }
}
 
// Function to insert the string to the buffer
// at point position
function insert(input, position) {
    let len = input.length;
    let i = 0;
     // If the point is not the gap check
    // and move the cursor to that point
    if (position !== gap_left) {
        move_cursor(position);
    }
     
    // Insert characters one by one
    while (i < len) {
        // If the gap is empty grow the size
        if (gap_right === gap_left) {
            let k = 10;
            grow(k, position);
        }
        // Insert the character in the gap and
        // move the gap
        buffer[gap_left] = input.charAt(i);
        gap_left++;
        i++;
        position++;
    }
}
let temp = "";
for (let i = 0; i < size; i++) {
    temp+=(buffer[i] + " ");
}
console.log("Initializing the gap buffer with size 10");
console.log(temp);
// Inserting a string to buffer
let input = "GEEKSGEEKS";
let position = 0;
 
insert(input, position);
 
console.log();
console.log("Inserting a string to buffer: GEEKSGEEKS");
console.log("Output: " + buffer.join(' '));
 
input = "FOR";
position = 5;
 
insert(input, position);
 
console.log();
console.log("Inserting a string to buffer: FOR");
console.log("Output: " + buffer.join(' '));


Output:

Initializing the gap buffer with size 10
_ _ _ _ _ _ _ _ _ _ 


Inserting a string to buffer: GEEKSGEEKS
Output: G E E K S G E E K S _ _ _ _ _ _ _ _ _ _ 

Inserting a string to buffer: FOR
Output: G E E K S F O R _ _ _ _ _ _ _ G E E K S 

Time complexity of insert: O(1) Time complexity of grow: O(n)

 Advantages: Gap Buffer Data Structure:

Advantages of Gap Buffer Data Structure:

  1. Dynamic: Gap Buffer data structure allows for dynamic insertions and deletions of elements, making it suitable for changing datasets.
  2. Efficient: Gap Buffer has an efficient time complexity for insertions and deletions, with an average time complexity of O(1) for inserting elements at the current cursor position.
  3. Space-efficient: Gap Buffer is a space-efficient data structure that uses a gap to represent empty space in the buffer, minimizing the number of memory reallocations required for insertions and deletions.
  4. Easy to implement: Gap Buffer is relatively simple to implement, making it a popular choice for text editors and other applications that require dynamic insertion and deletion of elements.
  5. Suitable for real-time: Gap Buffer is designed for real-time use, making it suitable for applications where low latency and fast insertions and deletions are important.
  6. Versatile: Gap Buffer can be used for a wide range of applications, including text editors, code editors, and other applications that require dynamic insertion and deletion of elements.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads