From 9d60e6e466bd8f61c23d4664eba05200376cc1b9 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 26 Oct 2009 20:47:23 +0100 Subject: [PATCH] A trivial change makes the new implementation O(log(N)) instead of O(log(N))+O(M) when there are M repeated scores! --- redis.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/redis.c b/redis.c index 0fb6b1e8..1c07dbc2 100644 --- a/redis.c +++ b/redis.c @@ -3855,7 +3855,10 @@ static void zslInsert(zskiplist *zsl, double score, robj *obj) { x = zsl->header; for (i = zsl->level-1; i >= 0; i--) { - while (x->forward[i] && x->forward[i]->score < score) + while (x->forward[i] && + (x->forward[i]->score < score || + (x->forward[i]->score == score && + compareStringObjects(x->forward[i]->obj,obj) < 0))) x = x->forward[i]; update[i] = x; } @@ -3888,34 +3891,34 @@ static int zslDelete(zskiplist *zsl, double score, robj *obj) { x = zsl->header; for (i = zsl->level-1; i >= 0; i--) { - while (x->forward[i] && x->forward[i]->score < score) + while (x->forward[i] && + (x->forward[i]->score < score || + (x->forward[i]->score == score && + compareStringObjects(x->forward[i]->obj,obj) < 0))) x = x->forward[i]; update[i] = x; } /* We may have multiple elements with the same score, what we need * is to find the element with both the right score and object. */ x = x->forward[0]; - while(x->score == score) { - if (compareStringObjects(x->obj,obj) == 0) { - for (i = 0; i < zsl->level; i++) { - if (update[i]->forward[i] != x) break; - update[i]->forward[i] = x->forward[i]; - } - if (x->forward[0]) { - x->forward[0]->backward = (x->backward == zsl->header) ? - NULL : x->backward; - } else { - zsl->tail = x->backward; - } - zslFreeNode(x); - while(zsl->level > 1 && zsl->header->forward[zsl->level-1] == NULL) - zsl->level--; - zsl->length--; - return 1; - } else { - x = x->forward[0]; - if (!x) return 0; /* end of the list reached, not found */ + if (compareStringObjects(x->obj,obj) == 0) { + for (i = 0; i < zsl->level; i++) { + if (update[i]->forward[i] != x) break; + update[i]->forward[i] = x->forward[i]; } + if (x->forward[0]) { + x->forward[0]->backward = (x->backward == zsl->header) ? + NULL : x->backward; + } else { + zsl->tail = x->backward; + } + zslFreeNode(x); + while(zsl->level > 1 && zsl->header->forward[zsl->level-1] == NULL) + zsl->level--; + zsl->length--; + return 1; + } else { + return 0; /* not found */ } return 0; /* not found */ }