List <BinHeapNode> binHeaps; // Для быстродействия можно отслеживать степени деревьяев, а не массив (есть стпепень - 1, нет - 0) public BinomialHeap() { binHeaps = new List <BinHeapNode>(); BinHeapNode tmp = new BinHeapNode(); binHeaps.Add(tmp); }
public BinomialHeap(int num) { binHeaps = new List <BinHeapNode>(); BinHeapNode tmp = new BinHeapNode(); Heap heaptmp = new Heap(num); tmp.SetHeap(heaptmp); binHeaps.Add(tmp); }
private void fix_carry(int indexDegree, Heap h3) { // Операция "фикс-перенос". // Считается, что di >= 2. if (binHeaps[indexDegree].size >= 2) { //Выполняем: // 1. d_i←d_i-2 if (binHeaps.Count - 1 < indexDegree + 1) { BinHeapNode tmp = new BinHeapNode(); binHeaps.Add(tmp); } if (binHeaps[indexDegree].size == 3) { h3.Merge(binHeaps[indexDegree].h2); binHeaps[indexDegree].SetHeap(null); //Merge(h3); switch (binHeaps[indexDegree + 1].size) // Бит, который стоит на месте степени дерева в числе { case 0: case 1: { //если в элемнете хранится 0 или 1 пирамида, то просто добавляем ее туда binHeaps[indexDegree + 1].SetHeap(h3); if (binHeaps[indexDegree + 1].size > 2) { fix_carry(indexDegree + 1, null); } break; } case 2: { //если в элементе хранится 2 пирамиды, то необходимо одну из них замерджить c HeapMerge. //int degreetmp = HeapMerge.degree; //HeapMerge.Merge(binHeaps[HeapMerge.degree].h2); //binHeaps[degreetmp].SetHeap(null); //Merge(h3); binHeaps[indexDegree + 1].size = 3; fix_carry(indexDegree + 1, h3); break; } default: break; } } else { Heap tmp1; binHeaps[indexDegree].h1.Merge(binHeaps[indexDegree].h2); // d[i] = d[i] - 2; tmp1 = binHeaps[indexDegree].h1; binHeaps[indexDegree].SetHeap(null); binHeaps[indexDegree].SetHeap(null); //Merge(tmp1); switch (binHeaps[indexDegree + 1].size) // Бит, который стоит на месте степени дерева в числе { case 0: case 1: { //если в элемнете хранится 0 или 1 пирамида, то просто добавляем ее туда binHeaps[indexDegree + 1].SetHeap(tmp1); if (binHeaps[indexDegree + 1].size > 2) { fix_carry(indexDegree + 1, null); } break; } case 2: { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////TODO: ЕСЛИ СЛЕДУЮЩИЙ БИТ СТАНЕТ 3, ТО ЭТО НИКАК НЕ ОБРАБАТЫВАЕТСЯ И ОН ОСТАНЕТСЯ ТРОЙКОЙ/////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //если в элементе хранится 2 пирамиды, то необходимо одну из них замерджить c HeapMerge. //int degreetmp = HeapMerge.degree; //HeapMerge.Merge(binHeaps[HeapMerge.degree].h2); //binHeaps[degreetmp].SetHeap(null); //Merge(tmp1); binHeaps[indexDegree + 1].size = 3; fix_carry(indexDegree + 1, tmp1); break; } default: break; } } // 2. d_(i+1)←d_(i+1)+1 // Нужно проверять, есть ли элемент (i+1): //if (binHeaps.Count - 1 < indexDegree + 1) //{ // //Если длина числа меньше, чем необходимый бит, то дописываем к числу 0. // d.Add(0); //} // d[indexDegree + 1] = d[indexDegree + 1] + 1; // Рекурсия?! Проверять то, что заменили вот здесь // Вот здесь merge между tmp и деревом, которое хранилось в ячейке indexDegree + 1 //if (binHeaps[indexDegree + 1].size >= 2) //{ // if (binHeaps[indexDegree + 1].size == 3) // { // fix_carry(indexDegree + 1, h3); // } // else // { // fix_carry(indexDegree + 1, null); // } //} } }
private void Merge(Heap HeapMerge) { //если индекс выходит за пределы листа binHeaps, то добавляет доп элемент (больше 1 не может быть) if (HeapMerge.degree > binHeaps.Count - 1) { BinHeapNode tmp = new BinHeapNode(); binHeaps.Add(tmp); } switch (binHeaps[HeapMerge.degree].size) // Бит, который стоит на месте степени дерева в числе { case 0: { //если в элемнете хранится 0 пирамида, то просто добавляем ее туда binHeaps[HeapMerge.degree].SetHeap(HeapMerge); break; } case 1: { //если в элемнете хранится 0 или 1 пирамида, то просто добавляем ее туда binHeaps[HeapMerge.degree].SetHeap(HeapMerge); break; } case 2: { //если в элементе хранится 2 пирамиды, то необходимо одну из них замерджить c HeapMerge. //int degreetmp = HeapMerge.degree; //HeapMerge.Merge(binHeaps[HeapMerge.degree].h2); //binHeaps[degreetmp].SetHeap(null); //Merge(HeapMerge); binHeaps[HeapMerge.degree].size = 3; break; } default: break; } // 1. ++di // 2. Находим db - первую экстремальную цифру {0,2,N/A} перед (дальше в списке) i int index_of_db = -1; for (int bit = HeapMerge.degree + 1; bit < binHeaps.Count; bit++) // Проходимся до конца списка { if ((binHeaps[bit].size == 0) || (binHeaps[bit].size == 2)) // TODO: Понять, что значит N/A число. { index_of_db = bit; break; } } // Если индекс не изменился, значит, после di нет экстремальных чисел bool is_db_NA = index_of_db == -1; // Флаг, который поднимается, если db не существует // 3. Находим da - первую экстремальную цифру {0,2,N/A} после (раньше в списке) i int index_of_da = -1; for (int bit = HeapMerge.degree - 1; bit >= 0; bit--) // Проходимся до начала списка { if ((binHeaps[bit].size == 0) || (binHeaps[bit].size == 2)) // TODO: Понять, что значит N/A число. { index_of_da = bit; break; } } // Если индекс не изменился, значит, после di нет экстремальных чисел bool is_da_NA = index_of_da == -1; // Флаг, который поднимается, если db не существует // 4. if di=3 or ( di=2 and db!=0 ) if (binHeaps[HeapMerge.degree].size == 3 || (binHeaps[HeapMerge.degree].size == 2 && (is_db_NA || binHeaps[index_of_db].size != 0))) { if (binHeaps[HeapMerge.degree].size == 3) { fix_carry(HeapMerge.degree, HeapMerge); } else { fix_carry(HeapMerge.degree, null); } } // 5. else if da = 2 else if (!is_da_NA) { if (binHeaps[index_of_da].size == 2) { fix_carry(index_of_da, null); } } }