// 合并两个二项队列 // H1包含合并的结果 BinQueue Merge(BinQueue H1, BinQueue H2) { BinTree T1, T2, Carry = NULL; int i, j; if((H1->CurrentSize + H2->CurrentSize) > MaxTrees) { printf("Merge would exceed capacity!"); return NULL; } H1->CurrentSize += H2->CurrentSize; for(i = 0, j = 1; j <= H1->CurrentSize; i++, j *= 2) { T1 = H1->TheTrees[i]; T2 = H2->TheTrees[i]; switch(!!T1 + 2 * !!T2 + 4 * !!Carry){ case 0: // nothing case 1: break; // only H1, do nothing case 2: // only H2 H1->TheTrees[i] = T2; H2->TheTrees[i] = NULL; break; case 4: // only Carry H1->TheTrees[i] = Carry; Carry = NULL; break; case 3: // H1 and H2 // 当合并两颗等高的二项树时 // 新的二项式的树高会 +1 // 这个新合并的二项树需要暂存起来,等待和下一个等高的二项树合并 Carry = CombineTree(T1, T2); H1->TheTrees[i] = H2->TheTrees[i] = NULL; Carry = NULL; break; case 5: // H1 and Carry Carry = CombineTree(T1, Carry); H1->TheTrees[i] = NULL; break; case 6: // T2 and Carry Carry = CombineTree(T2, Carry); H2->TheTrees[i] = NULL; break; case 7: // T1, T2 and Carry H1->TheTrees[i] = Carry; Carry = CombineTree(T1, T2); H2->TheTrees[i] = NULL; break; } } return H1; }
// 合并高度相同的二项树 BinTree CombineTree(BinTree T1, BinTree T2) { if(T1->Element > T2->Element) // 是要将根节点大的合并到根节点小的二项树上 return CombineTree(T2, T1); // 待合并的二项树中根节点的NextSibling一定为NULL // 现在T1 < T2 T2->NextSibling = T1->LeftChild; T1->LeftChild = T2; return T1; }
NiNode* MyClass::TEST_0046E720(NiNode* armor, NiNode* npc,UINT32 unk2,UINT32 unk3,UINT32 unk4,UINT32 unk5) { char prefix[10]; sprintf_s(prefix, "%08x ", armor); RenameNode(npc, armor, prefix); auto armornpc = CastNiNode(armor->GetObjectByName("NPC")); if(armornpc) for(int i=0; i<armornpc->m_children.m_arrayBufLen; ++i) { if(armornpc->m_children[i]) CombineTree(m_root, armornpc); } else CombineTree(m_root, armor); auto armorInSkeleton = CALL_MEMBER_FN(this, UNKNOWN_0046E720)(armor, npc, unk2, unk3, unk4, unk5); if(armorInSkeleton) { ArmorAttachInfo info; info.skeleton = npc; info.id = (UINT32)armor; info.prefix = prefix; npc->IncRef(); lockArmor.lock(); armorInfos.insert(std::make_pair(armorInSkeleton, info)); ResourceManager::get()->RegisterCallback(armorInSkeleton, OnArmorRelease); CWorld::getSingleton()->ScanAndAdd(info.id, prefix, npc, armor); lockArmor.unlock(); } else ClearNode(npc, prefix); return armorInSkeleton; }