固定长度结构重新排列:我应该使用数组还是链表
Fixed length structure re-arrange: should I use array or linked list?
此结构只包含256个无符号字符。唯一可能的操作是从中提取随机字符,并将它们放在结构前面。例如:
A= 'abcdef'
将字符2移到前面
A= 'cabdef'
我首先想到的是使用链接链接,这样它就可以作为队列工作。问题是,我听说数组在这些操作中比链表快得多。这是真的吗?
如您所述,对于移动操作,链表将为O(1),数组将为O。对于小型n
,阵列可能会更快,但唯一确定的方法是进行基准测试。
在这样的情况下,我会编写最清晰的代码,只有当它被证明是一个瓶颈时,我才会担心效率。
附言:我假设你已经有了一个指向你想要移动的角色的指针。如果不是这样,那么在链表中查找该字符将是O(n),您将失去它可能具有的任何优势。
使用数组。对于字符数据的存储来说,链表将是巨大而笨拙的。
链表是一种很好的方法,因为您不需要移动所有的中间元素。std::list
与splice()
结合使用效果良好。您需要一个迭代器来遍历要移到前面的元素:
#include <list>
#include <iostream>
#include "prettyprint.hpp"
int main()
{
std::list<int> x { 1, 4, 6, 7, 2 };
auto i = x.begin(); std::advance(i, 2); // i points to 6
std::cout << x << std::endl; // [1, 4, 6, 7, 2]
x.splice(x.begin(), x, i);
std::cout << x << std::endl; // [6, 1, 4, 7, 2]
}
(使用漂亮的打印机进行快速演示。)
正如其他人所说,这是否比随机访问容器更有效取决于您如何跟踪要移动的元素。
更新:根据Steve的评论,我也想提供一个原始的C阵列解决方案。它的优点是,您可以在O(1)时间内通过位置访问它,并且它需要最小的空间:
char y[] = { 'a', 'c', 'Q', '%', '5' };
std::cout << pretty_print_array(y) << std::endl; // [a, c, Q, %, 5]
std::rotate(y, y + 2, y + sizeof(y));
std::cout << pretty_print_array(y) << std::endl; // [Q, %, 5, a, c]
rotate
调用可以封装在一个函数中:
template <typename T, size_t N>
void bring_forward(T (& a)[N], size_t p) { std::rotate(a, a + p, a + N); }
在C++中,可以使用vector
而不是数组或链表。链表的复杂性是O(1),就像@Mark Ransom说的那样。使用矢量,可以使用命令rotate来执行所需的操作。复杂性由掉期的数量决定。
从MSDN,如何使用rotate:
const int VECTOR_SIZE = 8;
// Define a template class vector of strings
typedef vector<string> StrVector;
//Define an iterator for template class vector of strings
typedef StrVector::iterator StrVectorIt;
StrVector Tongue_Twister(VECTOR_SIZE);
StrVectorIt start, end, middle, it;
// location of first element of Tongue_Twister
start = Tongue_Twister.begin();
// one past the location last element of Tongue_Twister
end = Tongue_Twister.end();
// Initialize vector Tongue_Twister
Tongue_Twister[0] = "she";
Tongue_Twister[1] = "sells";
Tongue_Twister[2] = "sea";
Tongue_Twister[3] = "shells";
Tongue_Twister[4] = "by";
Tongue_Twister[5] = "the";
Tongue_Twister[6] = "sea";
Tongue_Twister[7] = "shore";
middle = start + 3; // start position for rotating elements
cout << "Before calling rotate" << endl;
// print content of Tongue_Twister
cout << "Try this Tongue Twister:";
for (it = start; it != end; it++)
cout << " " << *it;
// rotate the items in the vector Tongue_Twister by 3 positions
rotate(start, middle, end);
或者你可以用阵列来做:
// create an array of 9 elements and rotate the entire array.
int myArray[SIZE] = { 7, 8, 9, 1, 2, 3, 4, 5, 6, };
std::rotate(myArray, myArray + 3, myArray + SIZE);
这有多快?我不知道。我还没有对它进行基准测试。但它比手动交换数组元素要容易得多。
数组将为O(1)以查找项,为O(n)以将它和其他项移动到正确的位置。链表将为O(n)以查找项目,为O(1)以将所有内容移动到正确的位置。无论哪种方式,复杂性都是一样的。
它们都很容易实现,所以实现它们并运行测试,看看哪一个可以让你的程序在真实世界的数据中更快地运行。
C++数组是链表,因此如果您已经知道元素在哪里(即,上面有迭代器),那么将元素移动到列表的前面是很便宜的。使用向量会导致每次将元素推到整个列表前面时都会移动整个列表。
- 打印问题.我在数组中打印值时遇到一些问题
- 为什么我的数组双精度函数不起作用?
- 为什么我的 scanf() 没有在我的数组上迭代我的 for 循环?
- C++ - 块不移动,我的数组不起作用
- 如何为我的数组选择更大的数据类型?
- C ++程序如何返回我的数组或写入全局变量
- 为什么我的数组值与此处的全局变量不匹配?
- 为什么我的数组或函数不起作用?
- 为什么我的数组值会更新为随机值?
- 为什么我的数组输出一个不在其中的元素
- 我该如何循环遍历我的数组(缓冲区——包含一个文本文件),并将其打印成30字节的块
- 对数组进行排序时遇到问题。为什么我的数组无法正确排序?
- 我是否能够确定在部署一个程序后发生了什么,我在数组末尾写入?
- 无法将任何内容存储到我的数组中
- 这两个代码之间的差异(为什么我的数组也有额外的空间,即使我限制了它)
- 如何在FFT之后设置我的数组的频带
- 我正在尝试计算 char 数组中的内容,直到 null 终止,但每次编译时,我都会得到一个比我的数组大的数字
- 为什么我的数组说部分通过写入访问冲突?
- 如何动态分配我的数组,重新分配给两次,等等
- C++数组,我应该如何修复我的数组,它需要删除一个变量的所有倍数