zoukankan      html  css  js  c++  java
  • 内存自管理的链表

      能对内存管理的链表

       编程时会经常使用到链表这种结构,数组与链表这两种数据结构的区别以及优点不再赘言。在链表频繁使用时,可能会遇到这种问题,那就是可能要频繁的申请和释放内存,这样可能会造成内存碎片,对于很多程序是不希望看到的。那我在这里介绍我这两天写的一种链表,它能够消除内存频繁分配和释放、使用内存不连续的特点,当然水平有限,希望各位朋友提出宝贵意见,我能把这个数据结构和算法实现的更好,可供大家参考。

    (一)介绍一下普通的链表结构

    //节点的数据结构
    struct HNode
    {
        void* data;        //此节点所存放的对象的地址
        HNode* next;
        HNode* last;
    };
    
    //链表的数据结构
    struct HList
    {
        HNode* header;
        HNode* tail;
    };
    
    int hlist_empty(HList& list);
    int hlist_clear(HList& list);
    int hlist_push_back(HList& list, void* data);
    int hlist_push_front(HList& list, void* data);
    int hlist_insert(HList& list, void* data1, void* data2);
    int hlist_delete(HList& list, void* data);

    普通链表算法的实现:

    View Code
    #pragma once
    #include "stdafx.h"
    #include "list.h"
    
    //链表的初始化操作
    int hlist_empty(HList& list)
    {
        list.header = list.tail = 0;
        return 1;
    }
    
    //链表的清空操作,释放所有内存
    int hlist_clear(HList& list)
    {
        HNode* node = list.header;
        HNode* next;
        while (0 != node)
        {
            next = node->next;
            delete node;
            node = next;
        }
        return 1;
    }
    
    int hlist_push_back(HList& list, void* data)
    {
        HNode* newNode = new HNode;
        newNode->data = data;
        newNode->next = 0;
        newNode->last = list.tail;
        if (0 == list.header)//空链表
        {
            list.header = list.tail = newNode;
        } 
        else//非空链表
        {
            list.tail->next = newNode;
            list.tail = newNode;
        }
    
        return 1;
    }
    
    int hlist_push_front(HList& list, void* data)
    {
        HNode* newNode = new HNode;
        newNode->data = data;
        newNode->last = 0;
        newNode->next = list.header;
    
        if (0 == list.header)//空链表
        {
            list.header = list.tail = newNode;
        } 
        else
        {
            list.header->last = newNode;
            list.header = newNode;
        }
    
        return 1;
    }
    
    int hlist_insert(HList& list, void* data1, void* data2)
    {
        bool find = false;
        HNode* node = list.header;
        HNode* next;
        while (0 != node)
        {
            next = node->next;
            if(node->data == data1)
            {
                HNode* newNode = new HNode;
                newNode->data = data2;
                newNode->last = node;
                newNode->next = next;
                node->next = newNode;
                if (0 != next)
                {
                    next->last = newNode;
                }
                else
                {
                    list.tail = newNode;
                }
    
                find = true;
                break;
            }
            node = next;
        }
    
        if(find)
            return 1;
    
        return 0;
    }
    
    int hlist_delete(HList& list, void* data)
    {
        HNode* node = list.header;
        HNode* next;
        bool find = false;
        while (0 != node)
        {
            next = node->next;
            if(data == node->data)
            {
                if (node->last == 0 && node->next == 0)
                {
                    delete node;
                    list.header = list.tail = 0;
                } 
                else if(node->last == 0 && node->next != 0)
                {
                    delete node;
                    list.header = next;
                }
                else if(node->last != 0 && node->next == 0)
                {
                    
                    list.tail = node->last;
                    list.tail->next = 0;
                    delete node;
                }
                else
                {
                    node->last->next = next;
                    node->next->last = node->last;
                    delete node;
                }
                
                find = true;
                break;
            }
            node = next;
        }
    
        if (find)
        {
            return 1;
        }
        
        return 0;
    }

    链表的测试及使用:

    View Code
    // LinkDemo01.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <stdlib.h>
    #include "list.h"
    
    void print_list(HList& list);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        const unsigned int size = 256;
        int arr[size];
        for (int i = 0; i < size; i++)
        {
            arr[i] = i;
        }
    
        HList list;
        hlist_empty(list);
    
        for (int i = 0; i < size; i++)
        {
            //hlist_push_back(list, arr + i);
            //hlist_push_front(list, arr + i);
            hlist_push_back(list, arr + i);
            //hlist_push_front(list, arr + i);
            //hlist_insert(list, arr + i, arr + i + size / 2);
        }
    
        for (int i = 0 ; i < size; i+=2)
        {
            hlist_delete(list, arr + i);
        }
        print_list(list);
    
        hlist_clear(list);
        system("pause\n");
        return 0;
    }
    
    void print_list(HList& list)
    {
        printf("打印链表\n");
        int cnt = 0;
        HNode* node = list.header;
        HNode* next;
        while (0 != node)
        {
            next = node->next;
            printf("%6d", *((int*)(node->data)));
            if (++cnt % 10 == 0)
            {
                printf("\n");
            }
            node = next;
        }
    }

    (二)内存自管理的链表

    上边是用C语言实现的最简单的数据结构和算法了。下面介绍避免内存碎片的链表的数据结构和使用方法。

      

    #define Herror int
    
    
    //节点
    struct HNode
    {
        void* data;
        HNode* next;
        HNode* last;
    };
    
    //内容链表
    typedef struct tag_HLink
    {
        HNode* header;
        HNode* tail;
    }HLink;
    
    //删除链表
    typedef struct tag_HLinkDel
    {
        HLink del;
        HNode** buf;
        unsigned int size;
        int index;
        int nBuf;
    }HLinkDel;
    
    //链表管理
    typedef struct tag_HList
    {
        HLink    link;
        HLinkDel link_del;
    }HList;
    
    
    Herror hlink_empty(HLink& link);
    Herror hlink_push_back(HLink& link, HNode* newNode);
    Herror hlink_push_front(HLink& link, HNode* newNode);
    Herror hlink_insert(HLink& link, void* data1, HNode* newNode);
    Herror hlink_delete(HLink& link, void* data, HNode* &nodeDel);
    Herror hlink_find(HLink& link, void* data, HNode* &nodeFind);
    
    Herror hlinkdel_empty(HLinkDel& linkdel, unsigned int size = 1024, int nBuf = 16);
    Herror hlinkdel_clear(HLinkDel& linkdel);
    Herror hlinkdel_pop(HLinkDel& linkdel, HNode* &node);
    Herror hlinkdel_push(HLinkDel& linkdel, HNode* node);
    Herror hlinkdel_alloc(HLinkDel& linkdel);
    
    
    Herror hlist_emtpy(HList& list);
    Herror hlist_clear(HList& list);
    Herror hlist_push_back(HList& list, void* data);
    Herror hlist_push_front(HList& list, void* data);
    Herror hlist_insert(HList& list, void* data1, void* data2);
    Herror hlist_delete(HList& list, void* data);

      上述代码中的HNode节点与(一)中的一样。HLink与(一)的HList一样。而出现了一个HLinkDel和HList结构体,它是做什么用处呢?

      像(一)中的链表,在添加或者插入新节点时才分配内存,删除节点也是立即释放此节点的内存。在进行一系列操作之后,链表中的节点在内存中的位置可能会很乱。如果频繁的使用插入和删除操作,则会产生内存碎片。在上边的代码中,我们用HLinkDel这个结构体来管理所有需要的内存。在创建链表时,会预先分配1024个节点的内存,即1024 * sizeof(HNode)个字节。这个数组首尾相连构成了HLinkDel成员del链表。即一个HList对象里,里边有两个链表,一个是真正的正在使用的link对象,另一个是管理着已经分配好内存的,等待着供link使用的linkdel的del链表。

    (1)创建HList对象时,link为空,linkdel按照参数或者默认的为linkdel.buf创建16个HNode*的数组,全部赋值为0,再分配1024*sizeof(HNode)大小的内存块,其内存地址赋给linkdel.buf[0],内存块中的所有节点连接起来交给del链表。

    (2)link增加或者插入节点时,从linkdel对象的del链表中取出一个节点,给link使用,当然del链表中去掉此节点。

    (3)link删除一个节点时,把删除的节点交给linkdel对象,加入到它的del链表中。

    (4)在使用了一段时间后,发现linkdel中的del链表已经空了,那么表明,之前分配的内存已经用完了,那么我们给linkdel.buf[1]再分配1024 * Sizeof(HNode) * 2 的内存,再给linkdel的del链表使用。

    (5)在最终使用完后,直接将linkdel中的buf数组中指向的每个内存块释放,再释放buf数组,就可以了。

    实现代码如下:

    View Code
    #pragma once
    #include "stdafx.h"
    #include "HList.h"
    
    
    //内容链表
    Herror hlink_empty(HLink& link)
    { 
        link.header = 0;
        link.tail   = 0;
        return 1;
    }
    
    Herror hlink_push_back(HLink& link, HNode* newNode)
    { 
        newNode->last = link.tail;
        newNode->next = 0;
    
        if(link.tail == 0)
        {
            link.tail = link.header = newNode;
        }
        else
        {
            link.tail->next = newNode;
            link.tail = newNode;
        }
    
        return 1;
    }
    
    Herror hlink_push_front(HLink& link, HNode* newNode)
    { 
        newNode->last = 0;
        newNode->next = link.header;
    
        if (0 == link.header)
        {
            link.header = link.tail = newNode;
        } 
        else
        {
            link.header->last = newNode;
            link.header = newNode;
        }
    
        return 1;
    }
    
    Herror hlink_insert(HLink& link, void* data1, HNode* newNode)
    { 
        bool find = false;
        HNode* node = link.header;
        HNode* next;
        while (0 != node)
        {
            next = node->next;
            if(node->data == data1)
            {
                find = true;
                newNode->last = node;
                newNode->next = node->next;
    
                node->next = newNode;
                if(0 == next)
                {                
                    link.tail = newNode;
                }
                else
                {
                    node->next->last= newNode;
                }
                break;
            }
            node = next;
        }
        if(find)
            return 1;
        return 0;
    }
    
    Herror hlink_delete(HLink& link, void* data, HNode* &nodeDel)
    { 
        HNode* node = link.header;
        HNode* next;
        bool find = false;
        while (0 != node)
        {
            next = node->next;
            if(data == node->data)
            {
                find = true;
                nodeDel = node;
    
                /*if(next == 0)
                {
                    node->last->next = 0;
                }
                else
                {
                    next->last = node->last;
                    node->last->next = next;
                }*/
                if(0 == next && 0 == node->last)
                {
                    link.header = link.tail = 0;
                }
                else if (0 == next && 0 != node->last)
                {
                    node->last->next = 0;
                    link.tail = node->last;
                }
                else if (0 != next && 0 == node->last)
                {
                    node->next->last = 0;
                    link.header = node->next;
                }
                else
                {
                    next->last = node->last;
                    node->last->next = next;
                }
                
                break;
            }
            node = next;
        }
    
        return 1;
    }
    
    Herror hlink_find(HLink& link, void* data, HNode* &nodeFind)
    { 
        bool find = false;
        HNode* node = link.header;
        HNode* next;
    
        while (0 != node)
        {
            next = node->next;
            if(data == node->data)
            {
                nodeFind = node; 
                find = true;
                break;
            }
            node = next;
        }
    
        if(find)
            return 1;
        return 0;
    }
    
    //删除链表
    Herror hlinkdel_empty(HLinkDel& linkdel, unsigned int size, int nBuf)
    { 
        hlink_empty(linkdel.del);
        linkdel.size = size;
        linkdel.nBuf = nBuf;
        linkdel.index = -1;
    
        linkdel.buf = new HNode*[nBuf];
        for (int i = 0; i < nBuf; i++)
        {
            linkdel.buf[i] = 0;
        }
    
    
        hlinkdel_alloc(linkdel);
        return 1;
    }
    
    Herror hlinkdel_alloc(HLinkDel& linkdel)
    {    
        linkdel.index++;
        int n = linkdel.index;
        unsigned int len = linkdel.size * (1 << n);
        linkdel.buf[n] = new HNode[len];
        
        HNode* p;
        for (unsigned int i = 0; i < len; i++)
        {
            p = linkdel.buf[n] + i;
            p->data = 0;
            p->next = p + 1;
            p->last = p - 1;
        }
        p = linkdel.buf[n];
        p[len-1].next = p[0].last = 0;
        linkdel.del.header = p;
        linkdel.del.tail   = p + len - 1;
        return 1;
    }
    
    Herror hlinkdel_clear(HLinkDel& linkdel)
    { 
        for (int i = 0; i < linkdel.nBuf; i++)
        {
            delete []linkdel.buf[i];
        }
        delete []linkdel.buf;
        linkdel.buf = 0;
        hlink_empty(linkdel.del);
        linkdel.index = -1;
        linkdel.nBuf = 0;
        linkdel.size = 0;
    
        return 1;
    }
    
    Herror hlinkdel_pop(HLinkDel& linkdel, HNode* &node)
    { 
        HLink& del = linkdel.del;
        if(del.header != 0)
        {
            node = del.header;
    
            if(del.tail == node)
            {
                hlinkdel_alloc(linkdel);
            }
            else
            {
                del.header->next->last = 0;
                del.header = del.header->next;
            }        
        }
        else if(del.header == 0)
        {
            hlinkdel_alloc(linkdel);
            hlinkdel_pop(linkdel, node);
        }
        return 1;
    }
    
    Herror hlinkdel_push(HLinkDel& linkdel, HNode* node)
    { 
        node->last = linkdel.del.tail;
        node->next = 0;
        linkdel.del.tail->next = node;
        linkdel.del.tail = node;
        return 1;
    }
    
    
    //链表管理
    Herror hlist_emtpy(HList& list)
    { 
        hlink_empty(list.link);
        hlinkdel_empty(list.link_del);
        return 1;
    }
    
    Herror hlist_clear(HList& list)
    { 
        hlinkdel_clear(list.link_del);
        return 1;
    }
    
    Herror hlist_push_back(HList& list, void* data)
    { 
        HNode* newNode;
        hlinkdel_pop(list.link_del, newNode);
        newNode->data = data;
        hlink_push_back(list.link, newNode);
        return 1;
    }
    
    Herror hlist_push_front(HList& list, void* data)
    { 
        HNode* newNode;
        hlinkdel_pop(list.link_del, newNode);
        newNode->data = data;
        hlink_push_front(list.link, newNode);
        return 1;
    }
    
    Herror hlist_insert(HList& list, void* data1, void* data2)
    { 
        //产生新节点
        HNode* newNode;
        hlinkdel_pop(list.link_del, newNode);
        newNode->data = data2;
    
        //插入新节点
        hlink_insert(list.link, data1, newNode);
        return 1;
    }
    
    Herror hlist_delete(HList& list, void* data)
    { 
        //在内容链表中删除此节点
        HNode* nodeDel = 0;
        hlink_delete(list.link, data, nodeDel);
    
        //在删除链表中加入此节点
        if(nodeDel != 0)
        {
            hlinkdel_push(list.link_del, nodeDel);
        }
        else
        {
            return 0;
        }
        return 1;
    }

    测试代码如下:

    View Code
    // LinkDemo02.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <stdlib.h>
    #include <time.h>
    #include "HList.h"
    
    void print(HList& list);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        const int SIZE = 0xFFFF;
        int arr[SIZE];
        for (int i = 0; i < SIZE; i++)
        {
            arr[i] = i;
        }
    
        HList list;
        hlist_emtpy(list);
    
        time_t t1, t2;
        t1 = clock();
        for (int i = 0 ; i < SIZE; i++)
        {
            //hlist_push_front(list, arr + i);
            hlist_push_back(list, arr+i);
        }
        //for (int i = 0; i < SIZE / 2; i++)
        //{
        //    hlist_insert(list, arr + i, arr + SIZE/2 + i);
        //}
        for (int i = 0; i < SIZE/2; i++)
        {
            hlist_delete(list, arr + i * 2);
        }
        t2 = clock();
        print(list);
    
        //for (int i = 10; i < 20; i++)
        //{
        //    hlist_push_front(list, arr + i);
        //}
        //print(list);
    
        //for (int i = 20; i < 30; i++)
        //{
        //    hlist_insert(list, arr + 10, arr + i);
        //}
        //print(list);
    
        hlist_clear(list);
    
        printf("%d\n", t2 - t1);
    //    system("pause\n");
        return 0;
    }
    
    void print(HList& list)
    {
        printf("打印内容链表!\n");
        HNode* node = list.link.header;
    
        int i = 0;
        while (0 != node)
        {        
            printf("%5d->", *((int*)(node->data)));
            node = node->next;
            i++;
            if(i % 10 == 0)
            {
                printf("\n");
            }
        }
    }

    这两天全部时间都在写这个链表的代码了,从各方面我也考虑了很多,但是毕竟个人水平有限,希望大家多提修改意见,能让这个算法更好用。供更多人参考和使用。

    提前感谢所有的建议和批评!

  • 相关阅读:
    Spring4整合Hibernate5时不能自动生成表结构
    Unmapped Spring configuration files found.
    org.springframework.beans.factory.UnsatisfiedDependencyException
    The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server
    could not find class that it depends on; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
    [Java] JVM 在执行 main 方法前的行为
    [Java] JavaMail 查询邮件
    [Java] JavaMail 发送 html 格式、带附件的邮件
    [Java] JavaMail 简单案例
    [工作] 使在家办公(Work From Home)更有效率的建议
  • 原文地址:https://www.cnblogs.com/sdlypyzq/p/2933665.html
Copyright © 2011-2022 走看看