long CMuleListCtrl::GetInsertPos(wxUIntPtr data) { // Find the best place to position the item through a binary search int Min = 0; int Max = GetItemCount(); // Only do this if there are any items and a sorter function. // Otherwise insert at end. if (Max && m_sort_func) { // This search will find the place to position the new item // so it matches current sorting. // The result will be the position the new item will have // after insertion, which is the format expected by the InsertItem function. // If the item equals another item it will be inserted after it. do { int cur_pos = ( Max - Min ) / 2 + Min; int cmp = CompareItems(data, GetItemData(cur_pos)); // Value is less than the one at the current pos if ( cmp < 0 ) { Max = cur_pos; } else { Min = cur_pos + 1; } } while ((Min != Max)); } return Max; }
bool CMuleListCtrl::IsItemSorted(long item) { wxCHECK_MSG(m_sort_func, true, wxT("No sort function specified!")); wxCHECK_MSG((item >= 0) && (item < GetItemCount()), true, wxT("Invalid item")); bool sorted = true; wxUIntPtr data = GetItemData(item); // Check that the item before the current item is smaller (or equal) if (item > 0) { sorted &= (CompareItems(GetItemData(item - 1), data) <= 0); } // Check that the item after the current item is greater (or equal) if (sorted && (item < GetItemCount() - 1)) { sorted &= (CompareItems(GetItemData(item + 1), data) >= 0); } return sorted; }
void CIniEx::QuickSortRecursive(int nSection, int iLow, int iHigh, bool bAscending) { // Params renamed for easier comparison with literature int iLeft = iLow; int iRight = iHigh; // Important: Save Pivot-Element on Stack, instead of using GetAt(iPivot) in // "while('compare')-Loop". Original implementation by Attila Hajdrik used // GetAt(iPivot) in within the Loop // int iPivot = (iLow+iHigh) / 2; CString Pivot = m_Keys[nSection]->GetAt((iLow+iHigh) / 2); do { if( bAscending ) { while( CompareItems(m_Keys[nSection]->GetAt(iLeft), Pivot) < 0 ) iLeft++; while( CompareItems(Pivot, m_Keys[nSection]->GetAt(iRight)) < 0 ) iRight--; } else { while( CompareItems(m_Keys[nSection]->GetAt(iLeft), Pivot) > 0 ) iLeft++; while( CompareItems(Pivot, m_Keys[nSection]->GetAt(iRight)) > 0 ) iRight--; } if( iLeft <= iRight ) { Swap(nSection, iLeft, iRight); iLeft++; iRight--; } } while( iLeft <= iRight ); if( iLow < iRight ) QuickSortRecursive(nSection, iLow, iRight, bAscending); if( iLeft < iHigh ) QuickSortRecursive(nSection, iLeft, iHigh, bAscending); }
int isNeedNewUnit(int id, pItem ilist) { if(id < 1 || ! ilist) { debug("parameter error"); return ERR; } const pItem curent = (const pItem)&ilist[id]; const pItem prev = (const pItem)&ilist[id-1]; if(prev->len==0) return 0; return CompareItems(curent,prev); }
// Check two item set lists for equality int CompareItemSets(LR_ITEM_SET* one, LR_ITEM_SET* two) { while (one && two) { if (CompareItems(one->item, two->item) != 0) return 1; one = one->next; two = two->next; } if (one || two) return 1; return 0; }
bool CIniEx::Swap( int nSection, int nLeftIndex, int nRightIndex ) { // Ignore unnecessary swaps if( nLeftIndex == nRightIndex ) return false; if( nRightIndex == (nLeftIndex + 1) && CompareItems(m_Keys[nSection]->GetAt(nLeftIndex), m_Keys[nSection]->GetAt(nRightIndex)) == 0 ) return false; CString strHelp = m_Keys[nSection]->GetAt(nLeftIndex); m_Keys[nSection]->SetAt(nLeftIndex, m_Keys[nSection]->GetAt(nRightIndex) ); m_Keys[nSection]->SetAt(nRightIndex, strHelp ); strHelp = m_Values[nSection]->GetAt(nLeftIndex); m_Values[nSection]->SetAt(nLeftIndex, m_Values[nSection]->GetAt(nRightIndex)); m_Values[nSection]->SetAt(nRightIndex, strHelp); return true; }
// Simple parallel quick-sort. "first" and "last" are the first // and last items (inclusive) in the vector. void DepthVector::SortRange(Item *first, Item *last) { while (first < last) { if (last-first <= 100) { // Use the standard library function for small ranges. qsort(first, last-first+1, sizeof(Item), qsCompare); return; } // Select the best pivot from the first, last and middle item // by sorting these three items. We use the middle item as // the pivot and since the first and last items are sorted // by this we can skip them when we start the partitioning. Item *middle = first + (last-first)/2; if (CompareItems(first, middle) > 0) swapItems(first, middle); if (CompareItems(middle, last) > 0) { swapItems(middle, last); if (CompareItems(first, middle) > 0) swapItems(first, middle); } // Partition the data about the pivot. This divides the // vector into two partitions with all items <= pivot to // the left and all items >= pivot to the right. // Note: items equal to the pivot could be in either partition. Item *f = first+1; Item *l = last-1; do { // Find an item we have to move. These loops will always // terminate because testing the middle with itself // will return == 0. while (CompareItems(f, middle/* pivot*/) < 0) f++; while (CompareItems(middle/* pivot*/, l) < 0) l--; // If we haven't finished we need to swap the items. if (f < l) { swapItems(f, l); // If one of these was the pivot item it will have moved to // the other position. if (middle == f) middle = l; else if (middle == l) middle = f; f++; l--; } else if (f == l) { f++; l--; break; } } while (f <= l); // Process the larger partition as a separate task or // by recursion and do the smaller partition by tail // recursion. if (l-first > last-f) { // Lower part is larger gpTaskFarm->AddWorkOrRunNow(sortTask, first, l); first = f; } else { // Upper part is larger gpTaskFarm->AddWorkOrRunNow(sortTask, f, last); last = l; } } }
// Merge cells with the same contents. POLYUNSIGNED DepthVector::MergeSameItems() { DepthVector *v = this; POLYUNSIGNED N = v->nitems; Item *itemVec = v->vector; POLYUNSIGNED n = 0; POLYUNSIGNED i = 0; while (i < N) { PolyObject *bestShare = 0; // Candidate to share. MemSpace *bestSpace = 0; POLYUNSIGNED j; for (j = i; j < N; j++) { ASSERT (OBJ_IS_DEPTH(itemVec[i].pt->LengthWord())); // Search for identical objects. Don't bother to compare it with itself. if (i != j && CompareItems (& itemVec[i], & itemVec[j]) != 0) break; // The order of sharing is significant. // Choose an object in the permanent memory if that is available. // This is necessary to retain the invariant that no object in // the permanent memory points to an object in the temporary heap. // (There may well be pointers to this object elsewhere in the permanent // heap). // Choose the lowest hierarchy value for preference since that // may reduce the size of saved state when resaving already saved // data. // If we can't find a permanent space choose a space that isn't // an allocation space. Otherwise we could break the invariant // that immutable areas never point into the allocation area. MemSpace *space = gMem.SpaceForAddress(itemVec[j].pt); if (bestSpace == 0) { bestShare = itemVec[j].pt; bestSpace = space; } else if (bestSpace->spaceType == ST_PERMANENT) { // Only update if the current space is also permanent and a lower hierarchy if (space->spaceType == ST_PERMANENT && ((PermanentMemSpace *)space)->hierarchy < ((PermanentMemSpace *)bestSpace)->hierarchy) { bestShare = itemVec[j].pt; bestSpace = space; } } else if (bestSpace->spaceType == ST_LOCAL) { // Update if the current space is not an allocation space if (space->spaceType != ST_LOCAL || ! ((LocalMemSpace*)space)->allocationSpace) { bestShare = itemVec[j].pt; bestSpace = space; } } } POLYUNSIGNED k = j; // Remember the first object that didn't match. //.For each identical object set all but the one we want to point to // the shared object. for (j = i; j < k; j++) { ASSERT (OBJ_IS_DEPTH(itemVec[j].pt->LengthWord())); if (itemVec[j].pt == bestShare) { // This is the common object. bestShare->SetLengthWord(itemVec[j].L); // restore genuine length word ASSERT (OBJ_IS_LENGTH(bestShare->LengthWord())); } else { itemVec[j].pt->SetForwardingPtr(bestShare); /* an indirection */ ASSERT (itemVec[j].pt->ContainsForwardingPtr()); n++; } } ASSERT(! OBJ_IS_DEPTH(itemVec[i].pt->LengthWord())); i = k; } return n; }
static int qsCompare(const void *a, const void *b) { return CompareItems((const Item*)a, (const Item*)b); }
/** * Sort() performs a selection sort on list (it assumes list points to the head * of the list) to sort the elements into ascending order. It makes no * guarantees of the addresses of the list items after sorting, so any ListItem * referenced before a call to Sort() and after may contain different data. Its * second argument is a comparison function that calculates the ordering. This * function takes two const ListItem pointers and return 1 if the first one is * "larger", 0 if they're "equal", and -1 if the second one is "bigger". Since * sorting relies on understanding the data within the ListItem, the comparison * function is left up to the caller to define. This comparison function follows * the same return types as the one used for qsort(). See qsort()'s * documentation for further information. For consistency Sort() returns * SUCCESS if successful. There is no internal error checking and so will never * return anything else. */ int Sort(ListItem *list, int (*CompareItems)(const ListItem *, const ListItem *)) { /* * Declaring variables */ list = GetFirst(list); int listPointerCount = 0; ListItem *listptr; listptr = (ListItem *) (malloc(sizeof (ListItem))); listptr = list->nextItem; /* * Counts the length of the stack and makes counter according * to the length */ while (listptr->nextItem != NULL) { listPointerCount++; /* * We do this several times where we compare based on value at * the location of the pointer list. Depending on the value * returned by compare, we may swap the two pointers. */ if (CompareItems(listptr, list) == TRUE) { SwapData(list, listptr); if (list->previousItem == NULL) { /* * This increments until the counter is back to NULL. * Essentially determines how far to go by counter. */ while (listPointerCount != NULL) { listptr = listptr->nextItem; list = list->nextItem; listPointerCount--; } /* * This continues the search if not a NULL */ } else { listptr = listptr->previousItem; list = list->previousItem; } /* * This checks to see if the pointers are the same. If they are * then we do nothing just increment. */ } else { if (list->previousItem == NULL) { while (listPointerCount != NULL) { listptr = listptr->nextItem; list = list->nextItem; listPointerCount--; } } else { listptr = listptr->previousItem; list = list->previousItem; } } } /* * Repeat and step through the code (identical code) */ while (TRUE) { if (CompareItems(listptr, list) == TRUE) { SwapData(list, listptr); if (list->previousItem == NULL) { listptr = listptr->nextItem; list = list->nextItem; } else { listptr = listptr->previousItem; list = list->previousItem; } } else { if (list->previousItem == NULL) { listptr = listptr->nextItem; list = list->nextItem; } else { listptr = listptr->previousItem; list = list->previousItem; } } if (list->previousItem == NULL) { if (CompareItems(listptr, list) == TRUE) { SwapData(list, listptr); return FALSE; } else { return FALSE; } } } }
Rlist *SortRlist(Rlist *list, int (*CompareItems) ()) /* * Sorts an Rlist on list->item. A function CompareItems(i1,i2) * must be written for this particular item, which returns * true if i1 <= i2, false otherwise. * * after using this function passed parameter pointer will be lost * use returned pointer to access container */ { Rlist *p = NULL, *q = NULL, *e = NULL, *tail = NULL; int insize = 0, nmerges = 0, psize = 0, qsize = 0, i = 0; if (list == NULL) { return NULL; } insize = 1; while (true) { p = list; list = NULL; tail = NULL; nmerges = 0; /* count number of merges we do in this pass */ while (p) { nmerges++; /* there exists a merge to be done */ /* step `insize' places along from p */ q = p; psize = 0; for (i = 0; i < insize; i++) { psize++; q = q->next; if (!q) { break; } } /* if q hasn't fallen off end, we have two lists to merge */ qsize = insize; /* now we have two lists; merge them */ while (psize > 0 || (qsize > 0 && q)) { /* decide whether next element of merge comes from p or q */ if (psize == 0) { /* p is empty; e must come from q. */ e = q; q = q->next; qsize--; } else if (qsize == 0 || !q) { /* q is empty; e must come from p. */ e = p; p = p->next; psize--; } else if (CompareItems(p->item, q->item)) { /* First element of p is lower (or same); * e must come from p. */ e = p; p = p->next; psize--; } else { /* First element of q is lower; e must come from q. */ e = q; q = q->next; qsize--; } /* add the next element to the merged list */ if (tail) { tail->next = e; } else { list = e; } tail = e; } /* now p has stepped `insize' places along, and q has too */ p = q; } tail->next = NULL; /* If we have done only one merge, we're finished. */ if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ { return list; } /* Otherwise repeat, merging lists twice the size */ insize *= 2; } }
/* function closure(I): begin repeat for each item [A -> a*ZB, a] in I, each production Z -> y in G', and each terminal b in FIRST(Ba) such that [Z -> *y, b] is not in I do add [Z -> *y, b] to I; until no more items can be added to I; return I end; */ LR_ITEM_SET* Closure(LR_ITEM_SET* I, GRAMMAR_TABLE* G) { // J := I; LR_ITEM_SET* J = CopyItemSet(I); // repeat int stillAdding; do { stillAdding = 0; // for each item [A -> a*ZB, a] in J, LR_ITEM_SET* itr; for (itr = J; itr; itr = itr->next) { LR_ITEM item = itr->item; RULE rule = G->rules[item.production]; if (item.dot < rule.rhsLength) { int Z = rule.rhs[item.dot]; // each production Z -> y in G', int i; for (i = 0; i < G->numRules; i++) { if (G->rules[i].lhs == Z) { // and each terminal b in FIRST(Ba) int B = (item.dot + 1 < rule.rhsLength) ? rule.rhs[item.dot + 1] : 0; int b; for (b = 0; b < G->numTokens; b++) { int terminal = (b + 1) | K_TOKEN; if ((B && GetFirstTable(B, terminal, G) == 1) || ((!B || IsNullable(B)) && GetFirstTable(item.lookahead, terminal, G) == 1)) { // such that [Z -> *y, b] is not in J do LR_ITEM add; add.production = i; add.dot = 0; add.lookahead = terminal; LR_ITEM_SET* find; for (find = J; find; find = find->next) { if (CompareItems(find->item, add) == 0) break; } if (find == NULL) { // add [Z -> *y, b] to J; find = malloc(sizeof(LR_ITEM_SET)); find->item = add; find->next = J; J = find; stillAdding = 1; } } } } } } } // until no more items can be added to J; } while (stillAdding); // return J return Sort(J); }
// sort LR_ITEM_SET list for easy comparison LR_ITEM_SET* Sort(LR_ITEM_SET* I) { LR_ITEM_SET* itr; LR_ITEM* heap; int i, size; if (I == NULL) return I; // count elements [O(N)] size = 0; for (itr = I; itr; itr = itr->next) { size++; } // allocate heap [O(1)] heap = malloc(sizeof(LR_ITEM) * size); // add items to the heap [O(N log N)] for (itr = I, i = 0; itr; itr = itr->next, i++) { heap[i] = itr->item; int a = i; int b = (i-1)/2; while (a > 0 && CompareItems(heap[a], heap[b]) < 0) { SWAP_ITEMS(&heap[a], &heap[b]); a = b; b = (b-1)/2; } } // pop items off the heap [O(N log N)] for (itr = I; itr; itr = itr->next) { itr->item = heap[0]; size--; heap[0] = heap[size]; int j = 0; int a = 1; int b = 2; while (j < size && ((a < size && CompareItems(heap[j], heap[a]) > 0) || (b < size && CompareItems(heap[j], heap[b]) > 0))) { if (b < size && CompareItems(heap[a], heap[b]) > 0) { SWAP_ITEMS(&heap[b], &heap[j]); j = b; } else { SWAP_ITEMS(&heap[a], &heap[j]); j = a; } a = 2*j + 1; b = 2*j + 2; } } // free memory [O(1)] free(heap); return I; }
void CXmlItem::SortItems(const CString& sItemName, const CString& sKeyName, XI_SORTKEY nKey, BOOL bAscending) { if (!sItemName || !sKeyName) return; // 1. sort immediate children first CXmlItem* pXIItem = GetItem(sItemName); if (!pXIItem) return; // make sure item has key value if (!pXIItem->GetItem(sKeyName)) return; // make sure at least one sibling exists BOOL bContinue = (pXIItem->GetSibling() != NULL); while (bContinue) { CXmlItem* pXIPrev = NULL; CXmlItem* pXISibling = NULL; // get this again because we have to anyway // for subsequent loops pXIItem = GetItem(sItemName); POSITION pos = m_lstItems.Find(pXIItem); // reset continue flag so that if there are no // switches then the sorting is done bContinue = FALSE; pXISibling = pXIItem->GetSibling(); while (pXISibling) { int nCompare = CompareItems(pXIItem, pXISibling, sKeyName, nKey); if (!bAscending) nCompare = -nCompare; if (nCompare > 0) { // switch items if (pXIPrev) pXIPrev->m_pSibling = pXISibling; else // we're at the head of the chain { m_lstItems.SetAt(pos, pXISibling); // m_mapItems[sItemName] = pXISibling; } pXIItem->m_pSibling = pXISibling->m_pSibling; pXISibling->m_pSibling = pXIItem; pXIPrev = pXISibling; bContinue = TRUE; // loop once more } else { pXIPrev = pXIItem; pXIItem = pXISibling; } pXISibling = pXIItem->GetSibling(); // next } } // 2. sort children's children pXIItem = GetItem(sItemName); while (pXIItem) { pXIItem->SortItems(sItemName, sKeyName, nKey, bAscending); pXIItem = pXIItem->GetSibling(); } }