C语言 | Leetcode C语言题解之第432题全O(1)的数据结构

题目:

题解:

cpp 复制代码
//哈希+队列
//哈希检查是否存在
//双编标维护次数顺序
#define MAXSIZE 769/* 选取一个质数即可 */
typedef struct hashNode
{
    char* string;     //字符串
    int                       count;       //次数
    struct doubleListNode* dList;
    struct hashNode* next;      //保存链表表头
} hashMapList;

typedef struct
{
    hashMapList* hashHead[MAXSIZE];//定义哈希数组的大小
} MyHashMap;

typedef struct doubleListNode
{
    hashMapList* pHashMap;
    struct doubleListNode* prev;  //前一个指针域
    struct doubleListNode* next;  //下一个指针域
}doubleList;

typedef struct
{
    doubleList* front;       //头部指针
    doubleList* rear;        //尾部指针
    int count;
} MyQueueList;

typedef struct
{
    MyQueueList* doublelist;
    MyHashMap* hashmap;
} AllOne;


AllOne* allOneCreate()
{
    AllOne* newAllone = (AllOne*)malloc(sizeof(AllOne));
    MyHashMap* newHash = (MyHashMap*)malloc(sizeof(MyHashMap));
    MyQueueList* newList = (MyQueueList*)malloc(sizeof(MyQueueList));
    //哈希初始化
    for (int i = 0; i < MAXSIZE; i++)
    {
        newHash->hashHead[i] = NULL;
    }
    //队列初始化
    newList->front = NULL;
    newList->rear = NULL;
    newAllone->hashmap = newHash;
    newAllone->doublelist = newList;
    newAllone->doublelist->count = 0;
    return newAllone;
}

//哈希代码
hashMapList* isInHash(hashMapList* list, char* stringKey)
{
    hashMapList* nodeIt = list;
    //通过链表下遍历
    while (nodeIt != NULL)
    {
        if (strcmp(stringKey, nodeIt->string) == 0)
        {
            return nodeIt;
        }
        nodeIt = nodeIt->next;
    }
    return NULL;
}


hashMapList* myHashMapPut(MyHashMap* obj, char* stringKey, int count)
{
    hashMapList* newNode = (hashMapList*)malloc(sizeof(hashMapList));
    newNode->string = stringKey;
    newNode->next = NULL;
    newNode->count = count;
    if (obj->hashHead[stringKey[0] % MAXSIZE] != NULL)
    {
        //当前头链表不为空,则需要将后续的链表接上
        //需要主要这里表头也代表一个数据的值
        newNode->next = obj->hashHead[stringKey[0] % MAXSIZE];
    }
    //修改头链表
    obj->hashHead[stringKey[0] % MAXSIZE] = newNode;
    return newNode;
}

hashMapList* myHashMapGet(MyHashMap* obj, char* stringKey)
{
    hashMapList* hashMapIt = isInHash(obj->hashHead[stringKey[0] % MAXSIZE], stringKey);
    if (hashMapIt != NULL)
    {
        return hashMapIt;
    }
    return NULL;
}

void myHashMapRemove(MyHashMap* obj, char* key)
{
    hashMapList* nodePre = NULL;
    hashMapList* nodeIt = obj->hashHead[key[0] % MAXSIZE];


    //通过链表下遍历
    while (nodeIt != NULL)
    {
        if (strcmp(key, nodeIt->string) == 0)
        {
            break;
        }
        nodePre = nodeIt;
        nodeIt = nodeIt->next;
    }

    //找到了
    if (nodePre == NULL)
    {
        //等于表头
        obj->hashHead[key[0] % MAXSIZE] = nodeIt->next;
    }
    else
    {
        nodePre->next = nodeIt->next;
    }
    free(nodeIt);
}


void myHashMapFree(MyHashMap* obj)
{
    int i;
    hashMapList* freeIt;
    hashMapList* curIt;
    for (i = 0; i < MAXSIZE; i++)
    {
        if (obj->hashHead[i] != NULL)
        {
            freeIt = NULL;
            curIt = obj->hashHead[i];

            while (curIt != NULL)
            {
                freeIt = curIt;
                curIt = curIt->next;
                free(freeIt);
            }
            obj->hashHead[i] = NULL;
        }
    }
    free(obj);
}


//双链表代码
void myLinkedListFree(MyQueueList* obj)
{
    struct doubleListNode* nodeIt = obj->front;
    struct doubleListNode* nodeFree = obj->front;
    while (nodeIt != NULL)
    {
        nodeIt = nodeIt->next;
        free(nodeFree);
        nodeFree = nodeIt;
    }
    free(obj);
}


void doubleLsitMove(AllOne* obj, doubleList* targetlistIt, bool isUp)
{

    //数量等于2 直接比较双链表的头尾结点的值
    if (obj->doublelist->count == 2)
    {
        if (obj->doublelist->front->pHashMap->count >= obj->doublelist->rear->pHashMap->count)
        {
            return;
        }
        doubleList* temp = obj->doublelist->front;
        obj->doublelist->front = obj->doublelist->rear;
        obj->doublelist->rear  = temp;
        obj->doublelist->front->prev = NULL;
        obj->doublelist->front->next = obj->doublelist->rear;
        obj->doublelist->rear->prev  = obj->doublelist->front;
        obj->doublelist->rear->next  = NULL;
        return;
    }



    //至少3个结点才开始遍历
    if (isUp)
    {
        //递增 找到当前值 刚好比当前值大的位置
        if (targetlistIt != obj->doublelist->front)
        {
            doubleList* listItPre = targetlistIt->prev;
            //当前节点的cout大于 前一个结点的count值
            if(listItPre->pHashMap->count < targetlistIt->pHashMap->count)
            {
                //循环遍历查找
                while (listItPre != NULL && listItPre->pHashMap->count < targetlistIt->pHashMap->count)
                {
                    listItPre = listItPre->prev;
                }

                if (targetlistIt == obj->doublelist->rear)
                {
                    //特殊处理尾部特殊情况
                    obj->doublelist->rear       = targetlistIt->prev;
                    obj->doublelist->rear->next = NULL;
                }
                



                //插入位置是中间  listItPre > targetlistIt
                if (targetlistIt->prev != NULL)
                    targetlistIt->prev->next = targetlistIt->next;

                if (targetlistIt->next != NULL)
                    targetlistIt->next->prev = targetlistIt->prev;

                if (listItPre == NULL)
                {
                    //插入位置 是头部
                    targetlistIt->next              =    obj->doublelist->front;
                    obj->doublelist->front->prev    = targetlistIt;
                    obj->doublelist->front          = targetlistIt;
                    targetlistIt->prev              = NULL;
                }
                else
                {
                    targetlistIt->next          = listItPre->next;
                    targetlistIt->prev          = listItPre;
                    listItPre->next->prev       = targetlistIt;
                    listItPre->next             = targetlistIt;
                }
            }

        }
    }
    else
    {
        //递减 找到当前值 刚好比当前值小的位置
        if (targetlistIt != obj->doublelist->rear)
        {
            //向后移动
            doubleList* listItNxt = targetlistIt->next;
            //当前节点的cout大于 小于下一个结点的count值
            if (listItNxt->pHashMap->count > targetlistIt->pHashMap->count)
            {
                while (listItNxt != NULL && listItNxt->pHashMap->count > targetlistIt->pHashMap->count)
                {
                    listItNxt = listItNxt->next;
                }

                if (targetlistIt == obj->doublelist->front)
                {
                    //特殊处理头部特殊情况
                    obj->doublelist->front          = targetlistIt->next;
                    obj->doublelist->front->prev    = NULL;
                }

                //插入位置是中间  listItPre < targetlistIt
                if (targetlistIt->prev != NULL)
                    targetlistIt->prev->next = targetlistIt->next;

                if (targetlistIt->next != NULL)
                    targetlistIt->next->prev = targetlistIt->prev;

                if (listItNxt == NULL)
                {
                    //插入到队尾
                    obj->doublelist->rear->next     = targetlistIt;
                    targetlistIt->prev              = obj->doublelist->rear;
                    obj->doublelist->rear           = targetlistIt;
                    targetlistIt->next              = NULL;

                }
                else
                {
                    targetlistIt->prev = listItNxt->prev;
                    targetlistIt->next = listItNxt;
                    listItNxt->prev->next = targetlistIt;
                    
                }
            }
        }
    }
}

void myDobleListRemove(MyQueueList* obj, doubleList* targetlistIt)
{
    if (targetlistIt == obj->front && targetlistIt == obj->rear)
    {
        obj->front = NULL;
        obj->rear = NULL;
    }
    else if (targetlistIt == obj->front)
    {
        obj->front = obj->front->next;
        obj->front->prev = NULL;
    }
    else if (targetlistIt == obj->rear)
    {
        obj->rear = obj->rear->prev;
        obj->rear->next = NULL;
    }
    else
    {
        targetlistIt->prev->next = targetlistIt->next;
        targetlistIt->next->prev = targetlistIt->prev;
    }
    free(targetlistIt);
}

void allOneInc(AllOne* obj, char* key)
{
    hashMapList* hashMapIt = myHashMapGet(obj->hashmap, key);
    if (hashMapIt == NULL)
    {

        doubleList* newlist = (doubleList*)malloc(sizeof(doubleList));
        newlist->next = NULL;
        newlist->prev = NULL;
        //指向对应的hashMap
        //存入hashmap中,保存字符串做key,以及记录次数为1
        //双向指针 从hash表到双链表  从双链表到hash
        newlist->pHashMap = myHashMapPut(obj->hashmap, key, 1);
        newlist->pHashMap->dList = newlist;

        //插入到队尾处
        if (obj->doublelist->rear == NULL)
        {
            obj->doublelist->front = newlist;
            obj->doublelist->rear = newlist;
        }
        else
        {
            obj->doublelist->rear->next = newlist;
            newlist->prev = obj->doublelist->rear;
            obj->doublelist->rear = newlist;
        }
        obj->doublelist->count++;
    }
    else
    {
        hashMapIt->count++; //次数增加
        if (obj->doublelist->count >= 2)
        {
            doubleList* targetlistIt = hashMapIt->dList;
            doubleLsitMove(obj, targetlistIt, true);
        }
    }
}

void allOneDec(AllOne* obj, char* key)
{
    hashMapList* hashMapIt = myHashMapGet(obj->hashmap, key);
    if ((hashMapIt->count - 1) == 0)
    {
        doubleList* targetlistIt = hashMapIt->dList;
        myHashMapRemove(obj->hashmap, key);
        myDobleListRemove(obj->doublelist, targetlistIt);
        obj->doublelist->count--;
    }
    else
    {
        hashMapIt->count--;
        if (obj->doublelist->count >= 2)
        {
            doubleList* targetlistIt = hashMapIt->dList;
            doubleLsitMove(obj, targetlistIt, false);
        }
    }
}

char* allOneGetMaxKey(AllOne* obj)
{
    if (obj->doublelist->front == NULL)
    {
        return  "";
    }
    return obj->doublelist->front->pHashMap->string;
}

char* allOneGetMinKey(AllOne* obj)
{
    if (obj->doublelist->rear == NULL)
    {
        return  "";
    }
    return obj->doublelist->rear->pHashMap->string;
}



void allOneFree(AllOne* obj)
{
    myHashMapFree(obj->hashmap);
    obj->hashmap = NULL;
   myLinkedListFree(obj->doublelist);
   obj->doublelist =NULL;
   free(obj);
}
相关推荐
东方冷哥39 分钟前
考研数据结构——C语言实现归并排序
c语言·数据结构·考研
狗都不写1 小时前
洛谷P1789MC生存插火把
c语言·学习
panxianzhan2 小时前
VS开发 - 静态编译和动态编译的基础实践与混用
c语言·c++·windows·visual studio
拾柒SHY2 小时前
数据结构-线性表的单链式存储结构图解及C语言实现
c语言·数据结构
Stardep2 小时前
数据结构7—树(顺序存储二叉树—堆)含TOPK问题
c语言·数据结构·笔记·算法
Death2002 小时前
在 Qt 中构建和解析多层嵌套的 JSON 数据
c语言·开发语言·c++·qt·c#·json
霍霍哈嗨2 小时前
【基础算法总结】分治--快排+归并
开发语言·算法·leetcode
bossface3 小时前
线程LWP的概念和控制
linux·运维·服务器·c语言·c++
冉佳驹3 小时前
数据结构 ——— 顺序表oj题:编写函数,删除有序数组中的重复项
c语言·数据结构·算法
__AtYou__3 小时前
Golang | Leetcode Golang题解之第题432题全O(1)的数据结构
leetcode·golang·题解