如何二进制搜索结构向量并在适当的索引处插入
how to binary search a vector of structs and insert at appropriate index
我想做的事情:
我想要一个文本排序表(大小相等(,显示每个文本的出现次数。表格在文本插入表格时进行排序。当单词被插入到表中时,会检查它们是否已经存在,在这种情况下,它们的ref_count会递增。如果它们是新的,则其ref_count设置为1,并插入到右索引处的向量中,以确保表仍处于排序状态。
我做了什么:
我创建了一个结构和一个结构向量,定义如下。然后,我使用显示的二进制搜索来确定使用std::insert((函数的适当索引。
我的问题:我的二进制搜索实现没有返回正确的索引位置。
#define WORD_LENGTH 6
typedef struct RC_table {
char word[WORD_LENGTH+1];//+1 for ‘ ’
unsigned int ref_count;
}RC_table;
std::vector<RC_table>RC;
void update_RC(char *word_to_insert)
{
int index = 0;
bool found=binary_search_RC(word_to_insert, &index);
if (found == TRUE) {
//increment reference count
RC[index].ref_count++;
}
else {
//insert new word at index
RC_table new_entry;
memcpy(new_entry.word, word_to_insert, WORD_LENGTH);
new_entry.word[WORD_LENGTH] = ' ';
new_entry.ref_count = 1;
if(index==0)
RC.insert(RC.begin(),new_entry);
else if(index==RC.size()-1)
RC.insert(RC.end(),new_entry);
else {
RC.insert(RC.begin() + index +1, new_entry);
}
}
}
bool binary_search_RC(char *word, int *index) {
int left = 0;
int right = RC.size() -1;
int middle = (left + right) / 2;
bool found = false;
while (left<=right) {
middle = (left + right) / 2;
*index = middle;
if (strncmp(word, RC[middle].word, WORD_LENGTH) < 0) {
right = middle - 1;
}
else if(strncmp(word, RC[middle].word, WORD_LENGTH) > 0) {
left = middle + 1;
}
else {
found = true;
break;
}
}
*index = middle;
return found;
}
编辑:我尝试使用lower_bound((。它仍然没有给出预期的输出(即排序表(。
typedef struct RC_table {
char word[WORD_LENGTH+1];//+1 for ‘ ’
unsigned int ref_count;
bool operator<(const RC_table&r){
return word<r.word;
}
}RC_table;
插入表格使用:
auto itr=lower_bound(RC.begin(),RC.end(),new_enry);
RC.insert(itr,new_entry);
您的算法最大的问题是,您试图使用您认为可搜索的元素来保护分区的两侧。你不是这样做的;在最坏的找不到的情况下,分区可能(也将(最终陷入1/2的重复整数除法。当你这样做的时候,数学计算会容易得多:
- 分区的左端引用第一个元素,并被视为可疑元素
- 分区的右端指的是一个过去的元素。并且不被认为是可疑的
结果是一个更简单的算法,更容易理解,也更容易维护。
bool binary_search_RC(const char *word, int *index)
{
*index = 0;
int left = 0;
int right = static_cast<int>(RC.size());
bool found = false;
while (!found && left < right)
{
int middle = *index = left + (right-left) / 2;
int res = strncmp(word, RC[middle].word, WORD_LENGTH);
if (res < 0)
right = middle;
else if (res > 0)
*index = left = middle+1;
else
found = true;
}
return found;
}
将一个简单的小测试工具应用到实践中,它可以从简单的三个字母表中随机生成三个字符串。这应该会带来大量独特的插入,最终会有大量的发现。最后,我们将打印整个表格,如果这样做有效,最好对其进行排序。
代码
#include <iostream>
#include <vector>
#include <random>
#define WORD_LENGTH 6
typedef struct RC_table {
char word[WORD_LENGTH+1];//+1 for ‘ ’
unsigned int ref_count;
} RC_table;
std::vector<RC_table>RC;
bool binary_search_RC(const char *word, int *index)
{
*index = 0;
int left = 0;
int right = static_cast<int>(RC.size());
bool found = false;
while (!found && left < right)
{
int middle = *index = left + (right-left) / 2;
int res = strncmp(word, RC[middle].word, WORD_LENGTH);
if (res < 0)
right = middle;
else if (res > 0)
*index = left = middle+1;
else
found = true;
}
return found;
}
void update_RC(const char *word_to_insert)
{
int index = 0;
bool found = binary_search_RC(word_to_insert, &index);
if (found)
{
++RC[index].ref_count;
std::cout << "Found entry for " << word_to_insert;
std::cout << " (" << RC[index].ref_count << ")n";
}
else {
std::cout << "Adding entry for " << word_to_insert << 'n';
//insert new word at index
RC_table new_entry;
strncpy(new_entry.word, word_to_insert, WORD_LENGTH);
new_entry.word[WORD_LENGTH] = 0;
new_entry.ref_count = 1;
if(index==0)
RC.insert(RC.begin(),new_entry);
else if(index == RC.size())
RC.insert(RC.end(),new_entry);
else
RC.insert(RC.begin() + index, new_entry);
}
}
int main()
{
// generate some random values and start adding them. a few dozen
// with a severely limited alphabet should suffice.
const char alphabet[] = "abc";
std::mt19937 rng{ std::random_device{}() };
std::uniform_int_distribution<std::size_t> dist(0, sizeof alphabet - 2);
for (int i=0; i<50; ++i)
{
char word[WORD_LENGTH+1] = {};
for (int j=0; j<3; ++j)
word[j] = alphabet[ dist(rng) ];
update_RC(word);
}
// print the table
for (auto const& x : RC)
std::cout << x.word << " : " << x.ref_count << 'n';
}
输出(明显变化(
Adding entry for cab
Adding entry for cac
Adding entry for bcc
Adding entry for bbb
Adding entry for cbc
Adding entry for abb
Found entry for cab (2)
Adding entry for aba
Adding entry for cca
Adding entry for acc
Found entry for aba (2)
Found entry for bcc (2)
Adding entry for cbb
Found entry for cac (2)
Found entry for cac (3)
Adding entry for aaa
Found entry for acc (2)
Adding entry for bbc
Adding entry for baa
Adding entry for acb
Found entry for aaa (2)
Found entry for cca (2)
Found entry for baa (2)
Found entry for cbb (2)
Adding entry for aac
Found entry for cac (4)
Adding entry for aca
Adding entry for ccc
Found entry for bbc (2)
Adding entry for bba
Adding entry for bac
Adding entry for aab
Found entry for bac (2)
Found entry for aca (2)
Found entry for bcc (3)
Adding entry for caa
Found entry for aaa (3)
Found entry for bbc (3)
Found entry for caa (2)
Found entry for abb (2)
Found entry for baa (3)
Found entry for acc (3)
Found entry for bba (2)
Found entry for bbb (2)
Found entry for cbc (2)
Found entry for aaa (4)
Found entry for baa (4)
Adding entry for cba
Found entry for bac (3)
Found entry for bbc (4)
aaa : 4
aab : 1
aac : 1
aba : 2
abb : 2
aca : 2
acb : 1
acc : 3
baa : 4
bac : 3
bba : 2
bbb : 2
bbc : 4
bcc : 3
caa : 2
cab : 2
cac : 4
cba : 1
cbb : 2
cbc : 2
cca : 2
ccc : 1
我没有麻烦做数学运算,但把这些引用计数加起来,你应该会发现它们的总和是50,也就是我们执行的插入次数。
祝你好运。
相关文章:
- 将值插入到标准 c++ 数组的正确索引(升序)中
- 保持排序的数据结构,允许log N插入时间,并且可以返回我在log N中查找的元素的索引
- 如果索引不是整数,我们如何在 C++ 中插入哈希表
- 如何二进制搜索结构向量并在适当的索引处插入
- std::map 索引运算符与插入方法的性能
- 如何将值插入到 c++ boost::multiindex 集合的特定索引中,就像在 std::list 中一样
- 当索引位于末尾和空数组时,向数组插入元素时出现问题
- 在索引中插入节点:链接列表未正确返回列表
- 如何插入一个单词并将字母放在2D数组中的不同索引中
- 如何在C 中以给定索引列表中的项目插入项目
- 通过索引将字节插入mutli字节类型
- 通过索引操作员插入boost :: program_options :: variables_map
- 我们可以使用Back() - 值索引在其上执行向量插入
- 增强索引处的几何多边形插入点
- 通过索引快速搜索,并将插入顺序保持在C 中
- 使用boost::引用元组作为orderedunique索引的关键字时出现boost多索引插入错误
- 通过赋值运算符在索引处插入std::向量
- C++ std::lower_bound() 函数来查找索引排序向量的插入点
- Boost MultiIndexContainer,如何进行延迟索引以快速插入
- 提升多索引插入编译错误