Ejemplo n.º 1
0
RF_DiskQueueData_t *
rf_CvscanDequeue(void *q_in)
{
	RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in;
	long    range, i, sum_dist_left, sum_dist_right;
	RF_DiskQueueData_t *ret;
	RF_DiskQueueData_t *tmp;

	DO_CHECK_STATE(hdr);

	if (hdr->left_cnt == 0 && hdr->right_cnt == 0)
		return ((RF_DiskQueueData_t *) NULL);

	range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt, hdr->right_cnt));
	for (i = 0, tmp = hdr->left, sum_dist_left =
	    ((hdr->direction == rf_cvscan_RIGHT) ? range * hdr->change_penalty : 0);
	    tmp != (RF_DiskQueueData_t *) NULL && i < range;
	    tmp = tmp->next, i++) {
		sum_dist_left += hdr->cur_block - tmp->sectorOffset;
	}
	for (i = 0, tmp = hdr->right, sum_dist_right =
	    ((hdr->direction == rf_cvscan_LEFT) ? range * hdr->change_penalty : 0);
	    tmp != (RF_DiskQueueData_t *) NULL && i < range;
	    tmp = tmp->next, i++) {
		sum_dist_right += tmp->sectorOffset - hdr->cur_block;
	}

	if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right) {
		hdr->direction = rf_cvscan_LEFT;
		hdr->cur_block = hdr->left->sectorOffset + hdr->left->numSector;
		hdr->left_cnt = RF_MAX(hdr->left_cnt - 1, 0);
		tmp = hdr->left;
		ret = (ReqDequeue(&hdr->left)) /*->parent*/ ;
	} else {
		hdr->direction = rf_cvscan_RIGHT;
		hdr->cur_block = hdr->right->sectorOffset + hdr->right->numSector;
		hdr->right_cnt = RF_MAX(hdr->right_cnt - 1, 0);
		tmp = hdr->right;
		ret = (ReqDequeue(&hdr->right)) /*->parent*/ ;
	}
	ReBalance(hdr);

	if (hdr->left_cnt == 0 && hdr->right_cnt == 0
	    && hdr->burner != (RF_DiskQueueData_t *) NULL) {
		/*
		** restore low priority requests for next dequeue
		*/
		RF_DiskQueueData_t *burner = hdr->burner;
		hdr->nxt_priority = burner->priority;
		while (burner != (RF_DiskQueueData_t *) NULL
		    && burner->priority == hdr->nxt_priority) {
			RF_DiskQueueData_t *next = burner->next;
			RealEnqueue(hdr, burner);
			burner = next;
		}
		hdr->burner = burner;
	}
	DO_CHECK_STATE(hdr);
	return (ret);
}
LineComparable *AvlNode::Delete(double currentSweepPointX,
                                Inters::Line *key,
                                AvlNode *&root,
                                int &change,
                                cmp_t cmp) {
    // See if the tree is empty
    if (root == NULL) {
        // Key not found
        change = HEIGHT_NOCHANGE;
        return NULL;
    }

    // Initialize
    LineComparable *found = NULL;
    int decrease = 0;

    // Compare items and determine which direction to search
    cmp_t result = root->Compare(key, currentSweepPointX, cmp);
    dir_t dir = (result == MIN_CMP) ? LEFT : RIGHT;

    if (result != EQ_CMP) {
        // Delete from "dir" subtree
        found = Delete(key, root->mySubtree[dir], change, cmp);
        if (!found) return found;   // not found - can't delete
        decrease = result * change;    // set balance factor decrement
    } else {   // Found key at this node
        found = root->myData;  // set return value

        // ---------------------------------------------------------------------
        // At this point we know "result" is zero and "root" points to
        // the node that we need to delete.  There are three cases:
        //
        //    1) The node is a leaf.  Remove it and return.
        //
        //    2) The node is a branch (has only 1 child). Make "root"
        //       (the pointer to this node) point to the child.
        //
        //    3) The node has two children. We swap items with the successor
        //       of "root" (the smallest item in its rights subtree) and delete
        //       the successor from the rights subtree of "root".  The
        //       identifier "decrease" should be reset if the subtree height
        //       decreased due to the deletion of the successor of "root".
        // ---------------------------------------------------------------------

        if ((root->mySubtree[LEFT] == NULL) &&
            (root->mySubtree[RIGHT] == NULL)) {
            // We have a leaf -- remove it
            delete root;
            root = NULL;
            change = HEIGHT_CHANGE;    // height changed from 1 to 0
            return found;
        } else if ((root->mySubtree[LEFT] == NULL) ||
                   (root->mySubtree[RIGHT] == NULL)) {
            // We have one child -- only child becomes new root
            AvlNode *toDelete = root;
            root = root->mySubtree[(root->mySubtree[RIGHT]) ? RIGHT : LEFT];
            change = HEIGHT_CHANGE;    // We just shortened the subtree
            // Null-out the subtree pointers so we dont recursively delete
            toDelete->mySubtree[LEFT] = toDelete->mySubtree[RIGHT] = NULL;
            delete toDelete;
            return found;
        } else {
            // We have two children -- find successor and replace our current
            // data item with that of the successor
            root->myData = Delete(key, root->mySubtree[RIGHT],
                                  decrease, MIN_CMP);
        }
    }

    root->myBal -= decrease;       // update balance factor

    // ------------------------------------------------------------------------
    // Rebalance if necessary -- the height of current tree changes if one
    // of two things happens: (1) a rotation was performed which changed
    // the height of the subtree (2) the subtree height decreased and now
    // matches the height of its other subtree (so the current tree now
    // has a zero balance when it previously did not).
    // ------------------------------------------------------------------------
    //change = (decrease) ? ((root->myBal) ? balance(root) : HEIGHT_CHANGE)
    //                    : HEIGHT_NOCHANGE ;
    if (decrease) {
        if (root->myBal) {
            change = ReBalance(root);  // rebalance and see if height changed
        } else {
            change = HEIGHT_CHANGE;   // balanced because subtree decreased
        }
    } else {
        change = HEIGHT_NOCHANGE;
    }

    return found;
}