我已经四处搜索但无法真正理解或寻求帮助,因为这种迭代算法需要两个堆栈(包含left_Index和right_Index)。
主要的递归方式是将它放在一边直到left_Index> = right_Index,然后递归地为双方和每个子部分(如果这是有意义的)这样做,我不明白如何准确地这样做因为我要维护两个堆栈,需要看看它们之间的确切关系。
这个问题主要是由于我不理解正常的递归方法词的方式,虽然在并排查看它们时如何处理它,我总是不知所措。
关于为什么我这样做的背景故事: 试图解决从A到B的单词梯形问题,并决定建立一个BST,其中连接通过奇异的字符差异和长度连接。我从包含大量字典的文本文件中获取单词,并且由于我使用BST作为包含所有顶点的主列表,因此这是一个字典意味着每个插入都将按顺序排列因此树是右倾的(所以插入O(n ^ 2)的速度很慢,这是一个大阻碍)。我计划将数据存储在一个数组中,然后从中产生一个平衡的BST,因为我认为速度应该更快,因为插入将是O(n * logn),这看起来很棒。问题在于我不能使用递归方法,因为有很多数据导致堆栈溢出,所以我需要使用堆栈和循环迭代地进行迭代,但我发现它太难了。 / p>
我一开始的糟糕尝试:
while(lindx.the_front()< rindx.the_back())
{
mid =(lindx.the_front()+ rindx.the_back())/ 2;
dictionary.addVertex(矢量[MID]);
std :: cout<< "推动" << vector [mid]<< ' \ n&#39 ;; rindx.push(mid - 1);
}
这基本上是从我制作的链接堆栈中得到程序左半部分的1/2。 " the_front()"是第一个插入," the_back()"是列表中的最终/最新插入。我遇到的主要问题是理解如何让它重复一半以获得所有值。
我需要找到我过去的作业,我已经完成了这项工作,但代码是...... ...
void array2balanced(int array[], int lIndex, int rIndex)
{
//base case
if(lIndex > rIndex)
{
return;
}
//recursive cals
else
{
mid = (lIndex+rIndex)/2;
tree.insert(array[mid]);
array2balanced(array, lIndex, mid-1);
array2balanced(array, mid+1, rIndex);
}
}
更新 到目前为止进展
void balancedTree(std::vector<std::string> vector, dictionaryGraph &dictionary) // divide and conquer into tree?
{
linkedStack<int> lindx, rindx, midX;
unsigned int l_Index{ 0 }, r_Index{ vector.size() - 1 }, mid{ (l_Index + r_Index) / 2 };;
lindx.push(l_Index);
rindx.push(r_Index);
midX.push(mid);
int testCount{ 0 };
std::cout << "There are " << vector.size() << " words.\n";
while (!midX.empty())
{
mid = midX.pop();
l_Index = lindx.pop();
r_Index = rindx.pop();
std::cout << "inputted " << vector[mid] << '\n';
dictionary.addVertex(vector[mid]);
testCount++;
if (r_Index > l_Index)
{
midX.push((l_Index + mid) / 2);
lindx.push(l_Index);
rindx.push(mid - 1);
}
if (l_Index < r_Index)
{
midX.push((mid + r_Index) / 2);
lindx.push(mid + 1);
rindx.push(r_Index);
}
}
std::cout << testCount << " words were inputted...\n"; // To see how many were inserted
system("pause");
}
我遇到的问题是一些输入被重复,有些输入错过了。
答案 0 :(得分:0)
这个问题主要是由于我不理解正常的方式 递归方法的话,虽然并排看着它们 看看如何接近它,我总是不知所措。
这需要练习......并且可能会审查其他人的工作。
需要两个堆栈(包含left_Index和right_Index)。
道歉,我不明白为什么OP会这么想。我下面的演示只有一个名为'todo'的堆栈,也许你会发现这个想法很有用。
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <cassert>
#include "./BTree.hh" // code not provided, used in this MCVE to
// conveniently provide "showTallTreeView()"
typedef std::vector<int> IVec_t;
class T607_t
{
IVec_t m_sortedIVec; // sorted - created with for loop
IVec_t m_recursiveIVec; // extract from sorted by recursion
IVec_t m_iterativeIVec; // extract from sorted by iteration
public:
T607_t() = default;
~T607_t() = default;
int exec(int , char** )
{
fillShowSortedIVec();
fillShowRecursiveIVec();
fillShowIterativeIVec();
showResults();
return 0;
}
private: // methods
向量在T607_t类中,因此每个向量都可用于任何成员函数。
对于这个MCVE,我只创建“IVec_t m_sortedIVec;”并填写一个简单的for循环:
void fillShowSortedIVec()
{
for (int i=0; i<15; ++i)
m_sortedIVec.push_back (i*100); // create in sorted order
showIVec(m_sortedIVec, "\n m_sortedIVec :");
}
接下来(在这个MCVE中)是递归填充和显示,以及我对OP的递归方法的改编以产生递归插入序列:
// ///////////////////////////////////////////////////////////////
void fillShowRecursiveIVec()
{
assert(m_sortedIVec.size() > 0);
int max = static_cast<int>(m_sortedIVec.size()) - 1;
// use OP's recursive insert
array2balancedR (m_sortedIVec, 0, max);
// NOTE - 'sequence' is inserted to 'm_recursiveIVec'
// instead of into tree the op did not share
showIVec(m_recursiveIVec, "\n m_recursiveIVec:");
}
// recursive extract from: m_sortedIVec to: m_recursiveIVec
// my adaptation of OP's recursive method
void array2balancedR(IVec_t& array, int lIndex, int rIndex)
{
//base case
if(lIndex > rIndex)
{
return;
}
else //recursive calls
{
int mid = (lIndex+rIndex)/2;
m_recursiveIVec.push_back(array[mid]); // does this
// tree.insert(array[mid]); // instead of this
array2balancedR(array, lIndex, mid-1); // recurse left
array2balancedR(array, mid+1, rIndex); // recurse right
}
}
注意:我将“IVec_t&amp; array”作为参数留给了这个函数,因为OP的代码有它。在这个'class'包装器中,函数不需要通过递归传递数组,因为每个方法都可以访问实例数据。
下一步(在此MCVE中)是使用一种可能的迭代方法的填充和显示操作。我仔细地设计了这种迭代方法,以匹配OP的递归工作。
首先,我添加了一个'工具'(IndxRng_t)来简化迭代的'堆栈'捕获,以便以后处理。 (即“todo”)。
// //////////////////////////////////////////////////////////////
// iterative extract from m_sortedIVec to: m_iterativeIVec
class IndxRng_t // tool to simplify iteration
{
public:
IndxRng_t() = delete; // no default
IndxRng_t(int li, int ri)
: lIndx (li)
, rIndx (ri)
{}
~IndxRng_t() = default;
// get'er and set'er free. also glutton free. gmo free.
bool done() { return (lIndx > rIndx); } // range used up
int mid() { return ((lIndx + rIndx) / 2); } // compute
IndxRng_t left(int m) { return {lIndx, m-1}; } // ctor
IndxRng_t right(int m) { return {m+1, rIndx}; } // ctor
private:
int lIndx;
int rIndx;
};
void fillShowIterativeIVec()
{
assert(m_sortedIVec.size() > 0);
int max = static_cast<int>(m_sortedIVec.size()) - 1;
array2balancedI(m_sortedIVec, 0, max);
// 'sequence' inserted to 'm_iterativeIVec'
showIVec(m_iterativeIVec, "\n m_iterativeIVec:");
}
void array2balancedI(IVec_t& array, int lIndex, int rIndex)
{
std::vector<IndxRng_t> todo;
todo.push_back({lIndex, rIndex}); // load the first range
// iterative loop (No recursion)
do
{
if (0 == todo.size()) break; // exit constraint
// no more ranges to extract mid from
// fetch something to do
IndxRng_t todoRng = todo.back();
todo.pop_back(); // and remove from the todo list
if(todoRng.done()) continue; // lIndex > rIndex
int mid = todoRng.mid();
m_iterativeIVec.push_back(array[mid]); // do this
// tree.insert(array[mid]); // instead of this
todo.push_back(todoRng.right(mid) ); // iterate on right
todo.push_back(todoRng.left(mid) ); // iterate on left
}while(1);
}
这个mcve会生成一个结果显示:
void showResults()
{
assert(m_recursiveIVec.size() == m_sortedIVec.size());
assert(m_iterativeIVec.size() == m_sortedIVec.size());
std::cout << std::endl;
std::stringstream ss; // for btree use only
std::cout << "\n demo:\n create a BTree, "
<< std::flush;
std::cout << "\n Insert IVec_t " << std::endl;
BBT::BTree_t btree(ss);
std::cout << std::flush;
for (size_t i=0; i<m_iterativeIVec.size(); ++i)
btree.insertPL(m_iterativeIVec[i]);
std::cout << "\n iterative result:\n\n"
<< btree.showTallTreeView();
}
void showIVec(IVec_t& ivec, std::string lbl)
{
std::cout << lbl << std::endl;
for (auto it : ivec)
std::cout << std::setw(5) << it << std::flush;
std::cout << std::endl;
}
}; // class T607_t
int main(int argc, char* argv[])
{
T607_t t607;
return t607.exec(argc, argv);
}
我的输出(在Ubuntu 17.10,g ++ 7.2.0上),
m_sortedIVec :
0 100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400
m_recursiveIVec:
700 300 100 0 200 500 400 600 1100 900 800 1000 1300 1200 1400
m_iterativeIVec:
700 300 100 0 200 500 400 600 1100 900 800 1000 1300 1200 1400
demo:
create a BTree,
Insert IVec_t
iterative result:
BTree_t::showTallTreeView(): (balance: 0 sz: 15)
0
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300
1400
-----------------
答案 1 :(得分:0)
将排序后的数组转换为二进制搜索树(BST)的迭代JavaScript实现:
function sortedArrayToBstIteratively(nums) {
// use stack to iteratively split nums into node tuples and reuse values
const stack = []
// add root node to tree
const tree = { first: 0, last: nums.length - 1 }
stack.push(tree)
// split array in the middle and continue with the two halfs
while (stack.length > 0) {
const node = stack.pop()
if (node.last >= node.first) {
if (node.last === node.first) {
// node reaches a single leaf value (last == first)
node.value = nums[node.first]
} else {
// node has still valid indices to further split the array (last > first)
const middle = Math.ceil((node.first + node.last) / 2)
node.value = nums[middle]
node.left = { first: node.first, last: middle - 1 }
node.right = { first: middle + 1, last: node.last }
stack.push(node.left)
stack.push(node.right)
}
} else {
// node has no more valid indices (last < first), create empty leaf
node.value = null
}
delete node.first
delete node.last
}
// console.log(JSON.stringify(tree))
return tree
}