绳索数据结构(字符串快速拼接)
来源:互联网 发布:淘宝宝贝重复铺货 编辑:程序博客网 时间:2024/04/27 18:39
原文地址:Ropes Data Structure (Fast String Concatenation)
字符串连接是一种十分常见的操作。当字符串以传统的方式(例如字符数组)存储的时候,连接操作需要花费
我们可以利用绳索数据结构减少拼接花费的时间。
绳索数据结构
绳索是一个二叉树,这个二叉树的节点包含除叶子节点以外,节点左边字符的个数。叶子节点包含的是字符串断开的子字符串(子字符串的长度是由用户自己确定的)。
如下图所示:
上图说明了字符串在内存中的存储方式。每个叶子节点都包含了原字符串的子字符串,其他所有的节点包含了这个节点左边节点的字符数目。将字符的数目保存到左边的背后思想是查找第i个位置的字符所需要的成本最小化。
优点
- 绳索可以很明显地降低拼接的成本。
- 与数组不一样,绳索不需要大块连续的内存。
- 绳索不需要额外
O(n) 的空间做插入、删除、查询等操作。 - 如果要恢复最后一次拼接,那么可以在
O(1) 内移除树的根节点。
缺点
- 源码的复杂度增加了。
- 很容易出现bug。
- 存储父节点需要额外的空间。
- 访问第i个字符的时间增加了。
现在我们看一种情况,它可以解释为什么绳索法适用于大型字符串数组。
已知两个字符串a[]
与b[]
,在c[]
中拼接它们。
例子:
Input : a[] = "This is ", b[] = "an apple"Output : "This is an apple"Input : a[] = "This is ", b[] = "geeksforgeeks"Output : "This is geeksforgeeks"
方法一(普通法)
我们用字符串c[]
存储拼接后的结果。我们首先遍历a[]
然后将a[]
中的所有字符全部拷贝到c[]
中,然后再把b[]
全部拷到c[]
中。
// Simple C++ program to concatenate two strings#include <iostream>using namespace std;// Function that concatenates strings a[0..n1-1] // and b[0..n2-1] and stores the result in c[]void concatenate(char a[], char b[], char c[], int n1, int n2){ // Copy characters of A[] to C[] int i; for (i=0; i<n1; i++) c[i] = a[i]; // Copy characters of B[] for (int j=0; j<n2; j++) c[i++] = b[j]; c[i] = '\0';}// Driver codeint main(){ char a[] = "Hi This is geeksforgeeks. "; int n1 = sizeof(a)/sizeof(a[0]); char b[] = "You are welcome here."; int n2 = sizeof(b)/sizeof(b[0]); // Concatenate a[] and b[] and store result // in c[] char c[n1 + n2 - 1]; concatenate(a, b, c, n1, n2); for (int i=0; i<n1+n2-1; i++) cout << c[i]; return 0;}
输出:
This is geeksforgeeks
时间复杂度:
下面我们用绳索来解决这个问题。
方法二(绳索法)
绳索法可以在常量时间内将两个字符串拼接在一起。
- 创建一个根节点(这个节点存储要拼接的新字符串的根节点)。
- 标记这个节点的左孩子,这个字符串的根节点出现在首位。
- 标记这个节点的右孩子,这个字符串的根节点出现在第二位。
就是这样的,因为这个方法只要求建立新节点,所以时间复杂度是
考虑下图:
// C++ program to concatenate two strings using// rope data structure.#include <bits/stdc++.h>using namespace std;// Maximum no. of characters to be put in leaf nodesconst int LEAF_LEN = 2;// Rope structureclass Rope{public: Rope *left, *right, *parent; char *str; int lCount;};// Function that creates a Rope structure.// node --> Reference to pointer of current root node// l --> Left index of current substring (initially 0)// r --> Left index of current substring (initially n-1)// par --> Parent of current node (Initially NULL)void createRopeStructure(Rope *&node, Rope *par, char a[], int l, int r){ Rope *tmp = new Rope(); tmp->left = tmp->right = NULL; // We put half nodes in left subtree tmp->lCount = (r-l)/2; tmp->parent = par; // If string length is more if ((r-l) > LEAF_LEN) { tmp->str = NULL; node = tmp; int m = (l + r)/2; createRopeStructure(node->left, node, a, l, m); createRopeStructure(node->right, node, a, m+1, r); } else { node = tmp; int j = 0; tmp->str = new char[LEAF_LEN]; for (int i=l; i<=r; i++) tmp->str[j++] = a[i]; }}// Function that prints the string (leaf nodes)void printstring(Rope *r){ if (r==NULL) return; if (r->left==NULL && r->right==NULL) cout << r->str; printstring(r->left); printstring(r->right);}// Function that efficiently concatenates two strings// with roots root1 and root2 respectively. n1 is size of// string represented by root1.// root3 is going to store root of concatenated Rope.void concatenate(Rope *&root3, Rope *root1, Rope *root2, int n1){ // Create a new Rope node, and make root1 // and root2 as children of tmp. Rope *tmp = new Rope(); tmp->parent = NULL; tmp->left = root1; tmp->right = root2; root1->parent = root2->parent = tmp; tmp->lCount = n1; // Make string of tmp empty and update // reference r tmp->str = NULL; root3 = tmp;}// Driver codeint main(){ // Create a Rope tree for first string Rope *root1 = NULL; char a[] = "Hi This is geeksforgeeks. "; int n1 = sizeof(a)/sizeof(a[0]); createRopeStructure(root1, NULL, a, 0, n1-1); // Create a Rope tree for second string Rope *root2 = NULL; char b[] = "You are welcome here."; int n2 = sizeof(b)/sizeof(b[0]); createRopeStructure(root2, NULL, b, 0, n2-1); // Concatenate the two strings in root3. Rope *root3 = NULL; concatenate(root3, root1, root2, n1); // Print the new concatenated string printstring(root3); cout << endl; return 0;}
输出:
Hi This is geeksforgeeks. You are welcome here.
阅读全文
0 0
- 绳索数据结构(字符串快速拼接)
- 背阔肌(07):坐姿绳索划船
- 三维骨骼动画初探(绳索)
- Python合并(拼接) 字符串
- 拼接字符串:
- 字符串拼接
- 字符串拼接
- 字符串拼接
- 字符串拼接
- 拼接字符串
- 拼接字符串
- 拼接字符串
- 拼接字符串
- 字符串拼接
- 拼接字符串
- 字符串拼接
- 字符串拼接
- 拼接字符串
- Solr-4.10.X安装tomcat运行
- 程序员你伤不起(四)
- Python之禅
- python3 [入门基础实战] 爬虫入门之爬取糗事百科
- C语言编写规范之注释
- 绳索数据结构(字符串快速拼接)
- PHP设计模式教程
- 准备 KVM 实验环境
- hdu1546—Idiomatic Phrases Game(spfa)
- PHP网页后退时已过期处理办法
- ssh简单介绍
- 创建包围盒子
- 2017安徽程序设计竞赛总结
- 添加管理员admin