コード例 #1
0
/****************************************************************************
Desc:	Setup two child blocks for a root block.
****************************************************************************/
RCODE F_BtreeRoot::setupTree(
    FLMBYTE *		pucMidEntry,		// If !NULL entry to insert into root.
    eDynRSetBlkTypes		eBlkType,			// Leaf or non-leaf
    F_BtreeBlk **	ppLeftBlk,			// (out)
    F_BtreeBlk **	ppRightBlk)			// (out)
{
    RCODE			rc = NE_FLM_OK;
    F_BtreeBlk *	pLeftBlk = NULL;
    F_BtreeBlk *	pRightBlk = NULL;

    if (RC_BAD( rc = newBlk( &pLeftBlk, eBlkType)))
    {
        goto Exit;
    }

    if (RC_BAD( rc = newBlk( &pRightBlk, eBlkType)))
    {
        goto Exit;
    }

    if (eBlkType == ACCESS_BTREE_NON_LEAF)
    {
        ((F_BtreeNonLeaf *)pRightBlk)->lemBlk( lemBlk());
    }

    // Fix up the linkages

    pLeftBlk->nextBlk( pRightBlk->blkAddr());
    pRightBlk->prevBlk( pLeftBlk->blkAddr());
    lemBlk( pRightBlk->blkAddr());

    if (pucMidEntry)
    {

        // Add the midentry to the root block.  Search to position and insert.

        searchEntry( pucMidEntry);
        insertEntry( pucMidEntry, pLeftBlk->blkAddr());
    }
    m_uiLevels++;

    if (ppLeftBlk)
    {
        *ppLeftBlk = pLeftBlk;
    }
    if (ppRightBlk)
    {
        *ppRightBlk = pRightBlk;
    }

Exit:

    return( rc);
}
コード例 #2
0
/****************************************************************************
Desc:	Search a btree.  Position for get* or for insert.
****************************************************************************/
RCODE F_BtreeRoot::search(
    void *	pvEntry,
    void *	pvFoundEntry)
{
    RCODE			rc = NE_FLM_OK;
    FLMUINT		uiCurLevel = m_uiLevels - 1;	// Min 2 levels
    FLMUINT		uiBlkAddr;

    // Reset the stack - only needed for debugging.
    //f_memset( m_BTStack, 0, sizeof(F_BtreeBlk *) * FBTREE_MAX_LEVELS);

    // Search this root block.

    m_BTStack[ uiCurLevel] = this;
    (void) searchEntry( pvEntry, &uiBlkAddr);

    while( uiCurLevel--)
    {
        // Read the next block and place at uiCurLevel (backwards from FS).

        if( RC_BAD( rc = readBlk( uiBlkAddr,
                                  uiCurLevel ? ACCESS_BTREE_NON_LEAF : ACCESS_BTREE_LEAF,
                                  &m_BTStack[ uiCurLevel] )))
        {
            goto Exit;
        }

        // Set the rc - only for the leaf block, otherwise rc should be ignored.

        rc = m_BTStack[ uiCurLevel]->searchEntry( pvEntry, &uiBlkAddr,
                uiCurLevel ? NULL : pvFoundEntry);
    }

Exit:

    return( rc);
}
コード例 #3
0
/****************************************************************************
Desc:	Split the root block and make two new non-leaf blocks.
		The secret here is that the root block never moves (cheers!).
		This takes a little longer but is worth the work because the
		root block never goes out to disk and is not in the cache.
****************************************************************************/
RCODE F_BtreeRoot::split(
    void *			pvCurEntry,
    FLMUINT			uiCurChildAddr)
{
    RCODE				rc = NE_FLM_OK;
    FLMBYTE *		pucEntry;
    FLMBYTE *		pucChildAddr;
    F_BtreeBlk *		pLeftBlk;
    F_BtreeBlk *		pRightBlk;
    F_BtreeBlk *		pBlk;
    FLMUINT			uiChildAddr;
    FLMUINT			uiPos;
    FLMUINT			uiEntryCount = entryCount();
    FLMUINT			uiMid = (uiEntryCount + 1) >> 1;

    if (RC_BAD( rc = setupTree( NULL, ACCESS_BTREE_NON_LEAF,
                                &pLeftBlk, &pRightBlk)))
    {
        goto Exit;
    }

    // Call search entry once just to setup for insert.

    (void) pLeftBlk->searchEntry( ENTRY_POS( 0));

    // Take the entries from the root block and move into leafs.

    for (uiPos = 0; uiPos <= uiMid; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        pucChildAddr = pucEntry + m_uiEntrySize;
        uiChildAddr = (FLMUINT)FB2UD(pucChildAddr);

        if (RC_BAD( rc = pLeftBlk->insertEntry( pucEntry, uiChildAddr)))
        {
            goto Exit;
        }
    }

    // Call search entry once just to setup for insert.

    (void) pRightBlk->searchEntry( ENTRY_POS( 0));

    for (uiPos = uiMid + 1; uiPos < uiEntryCount; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        pucChildAddr = pucEntry + m_uiEntrySize;
        uiChildAddr = (FLMUINT)FB2UD(pucChildAddr);

        if ((rc = pRightBlk->searchEntry( pucEntry )) != NE_FLM_NOT_FOUND)
        {
            rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
            goto Exit;
        }

        if (RC_BAD( rc = pRightBlk->insertEntry( pucEntry, uiChildAddr)))
        {
            goto Exit;
        }
    }

    // Reset the root block and insert new midpoint.

    entryCount( 0);
    lemBlk( pRightBlk->blkAddr());	// Duplicated just in case.
    pucEntry = ENTRY_POS( uiMid);

    if ((rc = searchEntry( pucEntry )) != NE_FLM_NOT_FOUND)
    {
        rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
        goto Exit;
    }

    if (RC_BAD( rc = insertEntry( pucEntry, pLeftBlk->blkAddr() )))
    {
        goto Exit;
    }

    // Insert the current entry (parameters) into the left or right blk.
    // This could be done a number of different ways.
    (void) searchEntry( pvCurEntry, &uiChildAddr);
    if (RC_BAD( rc = readBlk( uiChildAddr, ACCESS_BTREE_NON_LEAF, &pBlk)))
    {
        goto Exit;
    }
    (void) pBlk->searchEntry( pvCurEntry);
    if (RC_BAD( rc = pBlk->insertEntry( pvCurEntry, uiCurChildAddr)))
    {
        goto Exit;
    }

Exit:

    return( rc);
}
コード例 #4
0
/****************************************************************************
Desc:	Move first half of entries into new block.  Reset previous block
		to point to new block.  Add new last entry in new block to parent.
		Fixup prev/next linkages.
****************************************************************************/
RCODE F_BtreeBlk::split(
    F_BtreeRoot *	pRoot,
    FLMBYTE *		pucCurEntry,		// (in) Contains entry to insert
    FLMUINT			uiCurBlkAddr,		// (in) Blk addr if non-leaf
    FLMBYTE *		pucParentEntry,	// (out) Entry to insert into parent.
    FLMUINT *		puiNewBlkAddr)		// (out) New blk addr to insert into parent.
{
    RCODE				rc = NE_FLM_OK;
    F_BtreeBlk *		pPrevBlk;
    F_BtreeBlk *		pNewBlk = NULL;
    FLMBYTE *		pucEntry = NULL;
    FLMBYTE *		pucMidEntry;
    FLMBYTE *		pucChildAddr;
    FLMUINT			uiChildAddr;
    FLMUINT			uiPrevBlkAddr;
    FLMUINT			uiMid;
    FLMUINT			uiPos;
    FLMUINT			uiMoveBytes;
    FLMBOOL			bInserted = FALSE;

    // Allocate a new block for the split.

    if (RC_BAD( rc = pRoot->newBlk( &pNewBlk, blkType() )))
    {
        goto Exit;
    }
    pNewBlk->AddRef();				// Pin the block - may get flushed out.


    // the last half into the new block, but that would force the parent
    // entry to be changed.  This may take a little longer, but it is much
    // more easier to code.

    // Call search entry once just to setup for insert.

    (void) pNewBlk->searchEntry( ENTRY_POS( 0));

    // get the count and move more then half into the new block.

    uiMid = (entryCount() + 5) >> 1;
    uiChildAddr = FBTREE_END;

    for (uiPos = 0; uiPos < uiMid; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        if (blkType() != ACCESS_BTREE_LEAF)
        {
            pucChildAddr = pucEntry + m_uiEntrySize;
            uiChildAddr = (FLMUINT)FB2UD(pucChildAddr);
        }

        // m_uiPosition automatically gets incremented.

        if (RC_BAD( rc = pNewBlk->insertEntry( pucEntry, uiChildAddr)))
        {
            RC_UNEXPECTED_ASSERT( rc);
            goto Exit;
        }
    }

    if (m_uiPosition < uiMid)
    {

        // Insert this entry now

        bInserted = TRUE;
        (void) pNewBlk->searchEntry( pucCurEntry);
        if (RC_BAD( rc = pNewBlk->insertEntry( pucCurEntry, uiCurBlkAddr)))
        {
            goto Exit;
        }
    }

    // Let caller insert into parent entry.  This rids us of recursion.

    f_memcpy( pucParentEntry, pucEntry, m_uiEntrySize);

    // Move the rest down

    pucEntry = ENTRY_POS( 0);
    pucMidEntry = ENTRY_POS( uiMid);

    entryCount( entryCount() - uiMid);
    uiMoveBytes = entryCount() * (m_uiEntrySize + m_uiEntryOvhd);
    flmAssert( uiMoveBytes < DYNSSET_BLOCK_SIZE - sizeof( FixedBlkHdr));
    f_memmove( pucEntry, pucMidEntry, uiMoveBytes);

    if( !bInserted)
    {

        // m_uiPosition -= uiMid;

        (void) searchEntry( pucCurEntry);
        if (RC_BAD( rc = insertEntry( pucCurEntry, uiCurBlkAddr)))
        {
            goto Exit;
        }
    }

    // VISIT: Could position stack to point to current element to insert.

    // Fixup the prev/next block linkages.

    if (prevBlk() != FBTREE_END)
    {
        if (RC_BAD( rc = pRoot->readBlk( prevBlk(), blkType(), &pPrevBlk )))
        {
            goto Exit;
        }

        pPrevBlk->nextBlk( pNewBlk->blkAddr());
        uiPrevBlkAddr = pPrevBlk->blkAddr();
    }
    else
    {
        uiPrevBlkAddr = FBTREE_END;
    }
    pNewBlk->prevBlk( uiPrevBlkAddr);
    pNewBlk->nextBlk( blkAddr());
    prevBlk( pNewBlk->blkAddr());

    *puiNewBlkAddr = pNewBlk->blkAddr();

Exit:

    if (pNewBlk)
    {
        pNewBlk->Release();
    }

    return( rc);
}
コード例 #5
0
ファイル: main.c プロジェクト: vrjunior/maze
int main() {
    setlocale(LC_ALL, "Portuguese");
    int lin, col;
    Point pos;
    Stack *ways;
    BoolPos currentSituation;
    int i;

    FILE *arquivo;
    arquivo = fopen("labirinto.txt", "r");

    if(arquivo == NULL) {
        printf("Erro ao carregar o labirinto, arquivo não pode ser aberto.");
        return 0;
    }

    fscanf(arquivo, "%i %i", &lin, &col);
    printf("Labirinto %i x %i\n\n", lin, col);

    // Alocate +1 to acomodate the \0 at end of final line
    char (*maze)[col] = (char(*)[col]) malloc((sizeof(char)*lin*col) + 1);

    for(i=0; i<lin; i++) {
        fscanf(arquivo, "%s", maze[i]);
    }

    if (!searchEntry(lin, col, maze, &pos)) {
        printf("\nNão há entrada para esse labirinto, impossível continuar");
        return 0;
    }

    ways = createStack(lin * col);
    push(ways, pos);
    maze[pos.x][pos.y] = 'v';
    while(maze[pos.x][pos.y] != MAZE_OUT) {
        checkPositions(&currentSituation, &pos, lin, col, maze);

        if(maze[pos.x][pos.y] == MAZE_WAY) {
            maze[pos.x][pos.y] = 'v'; //Move
        }

        printf("\nTentativa: %i x %i", pos.x, pos.y);

        if(currentSituation.left == 0 && currentSituation.bottom == 0 && currentSituation.right == 0 && currentSituation.top == 0) {
            if (!pop(ways, &pos)) {
                printf("\nEntrada encontrada não leva para uma saída!\n");

                if(searchEntry(lin, col, maze, &pos)) {
                    printf("Nova entrada encontrada! Resolvendo...\n");
                    push(ways, pos);
                }
                else {
                    printf("\n\nNão foi possível encontrar o caminhos a(s) entrada(s) encontrada(s) não levam à uma saída!\n");
                    break;
                }
            }
        } else {
            push(ways, pos);
        }
    }

    printf("\n\nLabirinto descoberto com sucesso!\nO caminho é:\n\n");

    while(pop(ways, &pos) == TRUE) {
        printf("%iº passo: %i x %i\n", ways->topo +1, pos.x, pos.y);
    }

    deinitStack(ways);
    printf("\n\n");

    free(maze);
    fclose(arquivo);

    system("Pause");
    return 0;
}
コード例 #6
0
 V*                  search      (const K& key)                  { Entry* e = searchEntry(key); return (e) ? &e->value : NULL; }
コード例 #7
0
 K*                  searchKey   (const K& key)                  { Entry* e = searchEntry(key); return (e) ? &e->key : NULL; }