📜  间隙缓冲区数据结构

📅  最后修改于: 2021-04-17 12:41:01             🧑  作者: Mango

间隙缓冲区是一种数据结构,用于以当前正在编辑的有效方式来编辑和存储文本。它也类似于数组,但是在数组中引入了一个间隙,用于处理游标处的多个更改。让我们假设一个间隙是另一个包含空白空间的数组。

示例:考虑一个示例,该示例的初始间隙大小为10,最初,数组或间隙的大小相同,因为我们将元素插入数组的方式类似,元素将插入间隙缓冲区中,唯一的区别是每次插入时间隙大小都会减小。

这是在前面插入字符的基本情况。现在,只要需要在某个位置插入一个字符,我们就可以使用left()right()将间隙向上移动到该位置,然后尝试插入该字符。

需要间隙缓冲区

  • 数组是一种数据结构,用于将项目存储在连续的内存位置。但是,它需要在数组末尾插入O(1),而在前面则需要O(n)时间,因为数组将向右移动n个位置,n是数组的长度。
  • 当涉及到文本编辑器时,我们需要一种更快的数据结构来进行插入和修改,因为光标位置存在多个更改。
  • 在最坏的情况下,数组将花费O(n)的时间进行插入或修改,如下例所示。
  • 为了在前面插入“ GEEKS”,通过移动数组留出空间来插入每个字符。

Gap Buffer中的基本操作

  • insert():这是一个用于在给定位置将字符插入文本的过程。它首先检查间隙是否为空,如果发现间隙为空,则调用过程grow()并调整间隙的大小,现在可以插入元素了。
  • left():这是用于将光标向左移动的过程,该光标点用作更改位置。

  • 右:这是用于将光标向右移动的过程,该光标点用作更改位置。

  • 增长:这是在间隙大小变为零时使用的过程,因此我们需要通过在所需位置插入间隙来调整数组的大小。

    间隙缓冲vs绳索

    现在,尽管它的插入花费O(1)时间,但是还有另一个函数grow()花费大约O(n)时间。因此,可能会认为这可能与绳索数据结构花费相同的时间,但是增长成本被其他更便宜的过程(如left(),right()和insert())的摊销成本所补偿。因此,这种数据结构易于实现,因此在文本编辑器中相对于诸如绳索之类的其他结构而言具有首选项。

    实现间隙缓冲区

    C++
    // C++ program of implementation of gap buffer
      
    #include  
    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


    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


    输出:
    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 
    

    插入的时间复杂度:O(1)
    增长的时间复杂度:O(n)