You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言跳表实现:删除函数故障排查求助

问题:C语言降序跳表删除函数的极端场景错误

我在C语言实现的降序跳表中遇到删除函数问题,多数测试用例正常,但存在错误结果及一处运行时错误。跳表需支持空链表、删除不存在元素(直接跳过)的场景,其余函数与结构基本正确,希望排查极端场景问题。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>

#define MaxLevel 65

int currLevel = 0;

typedef struct Node
{
    long long data;
    struct Node *next;
    struct Node *last;
    struct Node *up;
    struct Node *down;
} Node;

typedef struct 
{
    int level;
    struct Node *node;
} skipStep;

bool CoinFlip(long long k, int i) 
{
    return k >> (i - 1) & 1;
}

void skiplist_insert(Node *SL[], long long data) 
{
    int level = currLevel;
    Node *last = NULL;

    skipStep steps[MaxLevel];
    for (int i = 0; i < MaxLevel; i++) 
    {
        steps[i].level = 0;
        steps[i].node = SL[i];
    }

    Node *Head = SL[level];
    Node *tmp = Head->next;

    while (level > 0 && data > tmp->data) 
    {
        level--;
        Head = SL[level];
        tmp = Head->next;
    }

    while (level > 0) 
    {
        while (tmp != NULL) 
        {
            if (data > tmp->data) 
            {
                steps[level].level = level;
                if (last != NULL) 
                {
                    steps[level].node = last;
                }
                tmp = last->down;
                level--;
                break;
            }
            last = tmp;
            tmp = tmp->next;
        }
        if (tmp == NULL) 
        {                        
            steps[level].level = level;
            if (last != NULL) 
            {
                steps[level].node = last;
            }   
            tmp = last->down;
            level--;
        }
    }

    while (tmp != NULL) 
    {
        if (data > tmp->data) 
        {
            break;
        }
        last = tmp;
        tmp = tmp->next;
    }

    Node *newData = (Node *)malloc(sizeof(Node));
    newData->data = data;
    newData->up = NULL;
    newData->down = NULL;
    newData->last = NULL;
    newData->next = NULL;

    int k = 0;
    if (last == NULL) 
    {
        Head = SL[0];
        Node *headNext = Head->next;
        if (headNext != NULL) 
        {
            newData->next = headNext;
            headNext->last = newData;
            newData->last = Head;
        } 
        Head->next = newData;
        newData->last = Head;
    } 
    else if (tmp == NULL) 
    {
        last->next = newData;
        newData->last = last;
    } 
    else 
    {
        newData->next = tmp;
        tmp->last = newData;
        newData->last = last;
        last->next = newData;
    }

    while (CoinFlip(data, k + 1)) 
    {
        k++;
        if (k >= MaxLevel)
        { 
            break;
        }
        Node *newIndex = (Node *)malloc(sizeof(Node));
        newIndex->data = data;
        newIndex->down = newData;
        newData->up = newIndex;

        Node *node = steps[k].node;
        Node *nextIndex = node->next;

        node->next = newIndex;
        newIndex->last = node;
        newIndex->next = nextIndex;                
        if (nextIndex != NULL) 
        {
            nextIndex->last = newIndex;
        }          
        newData = newIndex;
        if (k > currLevel)
        { 
            currLevel = k;
        }
    }
}

Node *initSkipList(Node *skipList[]) 
{
    for (int i = 0; i < MaxLevel; i++) 
    {
        Node *newHead = (Node *)malloc(sizeof(Node));
        newHead->data = LLONG_MAX;
        newHead->down = NULL;
        newHead->up = NULL;
        newHead->next = NULL;
        newHead->last = NULL;
        skipList[i] = newHead;
    }
    return skipList[MaxLevel - 1];
}

Node *skiplist_search(Node *SL[], long long data) 
{
    if (SL[0]->next == NULL)
    {
        return NULL;
    }
    int level = currLevel;
    Node *Head = NULL;
    Node *tmp = NULL;
    Node *last = NULL;
    
    Head = SL[level];
    tmp = Head->next;
    long long endQuery = -1;
    while (level > 0 && data > tmp->data) 
    {
        level--;
        endQuery = tmp->data;
        Head = SL[level];
        tmp = Head->next;
    }

    while (level > 0 ) 
    {
        while (tmp != NULL) 
        {
            if (data > tmp->data) 
            {      
                level--;
                endQuery = tmp->data;
                tmp = last->down;
                break;
            }
            printf("%lld ", tmp->data);
            last = tmp;
            tmp = tmp->next;
        }
        if (NULL == tmp) 
        {
            tmp = last->down;
            endQuery = -1;
            level--;
        }
    }
    while (!level && tmp != NULL && tmp->data >= data)
    {
        printf("%lld ", tmp->data);
        tmp = tmp->next;
        if (tmp != NULL && tmp->data == data)
        {
            return tmp;
        }
        else if (tmp == NULL || tmp->data < data)
        {
            return NULL;
        }
    }
    return NULL;
}

Node *SlowGet(Node *SL[], long long data) 
{
    if (SL[0]->next == NULL || data > SL[0]->next->data)
    {
        return NULL;
    }
    
    Node *Head = SL[0];
    Node *tmp = Head->next;

    while (tmp != NULL && data < tmp->data) 
    {
        printf("%lld ", tmp->data);
        tmp = tmp->next;
    }

    if (tmp != NULL && data == tmp->data) 
    {
        return tmp;
    } 
    else 
    {
        return NULL;  
    }
}

void skiplist_delete(Node *SL[], long long data) 
{
    int level = currLevel;
    Node *Head = NULL;
    Node *tmp = NULL;
    Node *last = NULL;

    Head = SL[level];
    tmp = Head->next;
    long long endQuery = -1;

    while (level > 0 && data > tmp->data) 
    {
        level--;
        endQuery = tmp->data;
        Head = SL[level];
        tmp = Head->next;
    }

    while (level > 0) 
    {
        while (tmp != NULL) 
        {
            if (data > tmp->data)
            {
                level--;
                endQuery = tmp->data;
                tmp = last->down;
                break;
            }
            last = tmp;
            tmp = tmp->next;
        }
        if (tmp == NULL) 
        {
            tmp = last->down;
            endQuery = -1;
            level--;
        }
    }
    
    while (tmp != NULL) 
    {
        if (endQuery != -1)
        {
            if (tmp->data > endQuery) 
            {
                tmp = NULL;
                break;
            }
        }
        if (tmp->data == data) 
        {
            break;
        }
        tmp = tmp->next;
    }

    if (tmp == NULL) 
    {
        return;
    }
    level = 0;
    Node *t_last = NULL;
    Node *t_next = NULL;
    while (tmp->up != NULL) 
    {
        level++;
        tmp = tmp->up;
    }
    while (tmp != NULL) 
    {
        t_last = tmp->last;
        t_next = tmp->next;

        Node *t_down = tmp->down;

        if (t_last == NULL) 
        {
            return;
        }

        t_last->next = t_next;

        if (t_next != NULL)
            t_next->last = t_last;
        else
            t_last->next = NULL;

        if (t_last == SL[level] && t_next == NULL) 
        {
            currLevel--;
        }
        free(tmp);

        tmp = t_down;
        level--;
        if (currLevel < 0)
        {
            currLevel = 0;
        }
        if (level < 0)
        {
            level = 0;
        }
    }
}

int main() 
{
    int M;
    scanf("%d", &M);
    Node *SL[MaxLevel];
    Node *skipList = initSkipList(SL);

    for (int i = 0; i < M; ++i) 
    {
        int t;
        long long k;
        scanf("%d%lld", &t, &k);
        Node* node = NULL;
        switch (t) 
        {
            case 1:
                node = SlowGet(SL, k);
                if (node != NULL)
                {
                    printf("%lld", node->data);
                }
                else if (SL[0]->next == NULL || (node == NULL && k > SL[0]->next->data))
                {
                    printf("-1");
                }
                printf("\n");
                break;
            case 2:
                node = skiplist_search(SL, k);
                if (node != NULL)
                {
                    printf("%lld", node->data);
                }
                else if (SL[0]->next == NULL || (node == NULL && k > SL[0]->next->data))
                {
                    printf("-1");
                }
                printf("\n");
                break;
            case 3:
                skiplist_insert(SL, k);
                break;
            case 4:
                skiplist_delete(SL, k);
                break;
        }
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者Immortal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 20:44:50