zoukankan      html  css  js  c++  java
  • 数据结构-线性表

     

    线性表定义:
      1、0个或多个元素的集合
      2、元素之间是有序的
      3、元素个数有限
      4、元素数据的类型必须相同

    线性表是相同类型的n个数据元素的有限序列。
    逐项访问,顺序存储
    前驱 后继

    线性表在程序中表现为一种特殊的数据类型。

    线性表的操作则表现为一组函数。

    顺序表(线性表的顺序存储结构):

    SeqList.h

    #ifndef _SEQLIST_H_
    #define _SEQLIST_H_
    
    typedef void SeqList;
    typedef void SeqListNode;
    
    /*
        该方法用于创建并且返回一个空的线性表
    */
    SeqList* SeqList_Create(int capacity);
    
    /*
        该方法用于销毁一个线性表list
    */
    void SeqList_Destroy(SeqList* list);
    
    /*
        该方法用于将一个线性表list中的所有元素清空
        使得线性表回到创建时的初始状态
    */
    void SeqList_Clear(SeqList* list);
    
    /*
        该方法用于返回一个线性表list中的所有元素个数
    */
    int SeqList_Length(SeqList* list);
    
    
    /*
        返回线性表的最大容量 
    */ 
    int SeqList_Capacity(SeqList* list);
    
    /*
        该方法用于向一个线性表list的pos位置处插入新元素node
        返回值为1表示插入成功,0表示插入失败
    */
    int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);
    
    /*
        该方法用于获取一个线性表list的pos位置处的元素
        返回值为pos位置处的元素,NULL表示获取失败
    */
    SeqListNode* SeqList_Get(SeqList* list, int pos);
    
    /*
        该方法用于删除一个线性表list的pos位置处的元素
        返回值为被删除的元素,NULL表示删除失败
    */
    SeqListNode* SeqList_Delete(SeqList* list, int pos);
    
    #endif

    SeqList.c

    #include <stdio.h>
    #include <malloc.h>
    #include "SeqList.h"
    
     /**
     头文件中定义为void 
     实现时定义真实的类型
     
     数据封装
     
     1、对外不用关心list,listNode的真实类型 
     2、不会产生误操作 
     
     */
     
    typedef unsigned int TSeqListNode; //存储地址,这样可以适用于任何数据类型,更通用 
    
    typedef struct _tag_SeqList
    {
        int capacity;
        int length;
        TSeqListNode* node;
    } TSeqList;
    
    SeqList* SeqList_Create(int capacity) // O(1)
    {
        TSeqList* ret = NULL;
        
        if( capacity >= 0 )
        {
            //结构体本身+数组 
            ret = (TSeqList*)malloc(sizeof(TSeqList) + sizeof(TSeqListNode) * capacity);
        }
        
        if( ret != NULL )
        {
            ret->capacity = capacity;
            ret->length = 0;
            ret->node = (TSeqListNode*)(ret + 1);
        }
        
        return ret;
    }
    
    void SeqList_Destroy(SeqList* list) // O(1)
    {
        free(list);
    }
    
    void SeqList_Clear(SeqList* list) // O(1)
    {
        TSeqList* sList = (TSeqList*)list;
        
        if( sList != NULL )
        {
            sList->length = 0;
        }
    }
    
    int SeqList_Length(SeqList* list) // O(1)
    {
        TSeqList* sList = (TSeqList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->length;
        }
        
        return ret;
    }
    
    int SeqList_Capacity(SeqList* list) // O(1)
    {
        TSeqList* sList = (TSeqList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->capacity;
        }
        
        return ret;
    }
    
    // pos 从0开始算起 
    int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) // O(n) 
    {
        TSeqList* sList = (TSeqList*)list;
        int ret = (sList != NULL);
        int i = 0;
        
        ret = ret && (sList->length + 1 <= sList->capacity);
        ret = ret && (0 <= pos);
        
        if( ret )
        {
            if( pos >= sList->length )
            {
                pos = sList->length;
            }
            
            for(i=sList->length; i>pos; i--)
            {
                sList->node[i] = sList->node[i-1];
            }
            
            sList->node[i] = (TSeqListNode)node;
            
            sList->length++;
        }
        
        return ret;
    }
    
    SeqListNode* SeqList_Get(SeqList* list, int pos) // O(1) 
    {
        TSeqList* sList = (TSeqList*)list;
        SeqListNode* ret = NULL;
        
        if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
        {
            ret = (SeqListNode*)(sList->node[pos]);
        }
        
        return ret;
    }
    
    SeqListNode* SeqList_Delete(SeqList* list, int pos) // O(n)
    {
        TSeqList* sList = (TSeqList*)list;
        SeqListNode* ret = SeqList_Get(list, pos);
        int i = 0;
        
        if( ret != NULL )
        {
            for(i=pos+1; i<sList->length; i++)
            {
                sList->node[i-1] = sList->node[i];
            }
            
            sList->length--;
        }
        
        return ret;
    }

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "SeqList.h"
    
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    
    int main(int argc, char *argv[]) 
    {
        SeqList* list = SeqList_Create(5);
        
        int i = 0;
        int j = 1;
        int k = 2;
        int x = 3;
        int y = 4;
        int z = 5;
        int index = 0;
        
       /**
       找不到  TSeqList 因为在 SeqList.c 中定义 
        TSeqList *a = (TSeqList*)list;
        a->length = 0;
       */
       
        // 由于list是void*类型,所以不被允许,更加安全 
          // list->length = 0; 
        
        SeqList_Insert(list, &i, 0);
        SeqList_Insert(list, &j, 0);
        SeqList_Insert(list, &k, 0);
        SeqList_Insert(list, &x, 0);
        SeqList_Insert(list, &y, 0);
        SeqList_Insert(list, &z, 0);
        
        for(index=0; index<SeqList_Length(list); index++)
        {
            int* p = (int*)SeqList_Get(list, index);
            
            printf("%d
    ", *p);
        }
        
        printf("
    ");
        
        while( SeqList_Length(list) > 0 )
        {
            int* p = (int*)SeqList_Delete(list, 0);
            
            printf("%d
    ", *p);
        }
        
        SeqList_Destroy(list);
        
        return 0;
    }

    优点:

      无需为线性表中的逻辑关系增加额外的空间

      可以快速获取表中合法位置的元素

    缺点:

      插入和删除需要移动大量的元素。

      当线性表长度变化较大时难以确定存储空间的容量(浪费空间)。

    单链表(线性表的链式存储

    链式存储定义:
      为了表示每个数据元素与其后继元素之间的逻辑关系,每个元素除了存储本身的信息外,
      还需要存储其直接后续信息。

    节点:数据域+指针域

    n个节点链接成一个链式线性表的结构叫做链表。

    当每个节点只包含一个指针域时,叫做单链表。

    表头节点:
      链表中第一个节点(但不是数据元素), 包含指向第一个数据元素的指针以及链表的一些自身信息.

    数据节点:
      链表中代表数据元素的节点, 包含指向下一个数据元素的指针和数据元素的信息。

    尾节点:
      链表中最后一个数据节点, 其下一元素指针为空,表示无后继.


    头插法:每次都从链表头部插入
    尾插法:每次都从链表尾部插入

    LinkList.c

    #include <stdio.h>
    #include <malloc.h>
    #include "LinkList.h"
    
    typedef struct _tag_LinkList
    {
        LinkListNode header;
        int length;
    } TLinkList;
    
    LinkList* LinkList_Create() // O(1)
    {
        TLinkList* ret = (TLinkList*)malloc(sizeof(TLinkList));
        
        if( ret != NULL )
        {
            ret->length = 0;
            ret->header.next = NULL;
        }
        
        return ret;
    }
    
    void LinkList_Destroy(LinkList* list) // O(1)
    {
        free(list);
    }
    
    void LinkList_Clear(LinkList* list) // O(1)
    {
        TLinkList* sList = (TLinkList*)list;
        
        if( sList != NULL )
        {
            sList->length = 0;
            sList->header.next = NULL;
        }
    }
    
    int LinkList_Length(LinkList* list) // O(1)
    {
        TLinkList* sList = (TLinkList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->length;
        }
        
        return ret;
    }
    
    int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) // O(n)
    { 
        TLinkList* sList = (TLinkList*)list;
        int ret = (sList != NULL) && (pos >= 0) && (node != NULL);
        int i = 0;
        
        if( ret )
        {
            LinkListNode* current = (LinkListNode*)sList;
            
            for(i=0; (i<pos) && (current->next != NULL); i++)
            {
                current = current->next;
            }
            
            node->next = current->next;
            current->next = node;
            
            sList->length++;
        }
        
        return ret;
    }
    
    LinkListNode* LinkList_Get(LinkList* list, int pos) // O(n)
    {
        TLinkList* sList = (TLinkList*)list; //转换成不同的类型,则可以访问不同的数据 
        LinkListNode* ret = NULL;
        int i = 0;
        
        if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
        {
            //转换成不同的类型,则可以访问不同的数据 
            LinkListNode* current = (LinkListNode*)sList;
            
            for(i=0; i<pos; i++)
            {
                current = current->next;
            }
            
            ret = current->next;
        }
        
        return ret;
    }
    
    LinkListNode* LinkList_Delete(LinkList* list, int pos) // O(n)
    {
        TLinkList* sList = (TLinkList*)list;
        LinkListNode* ret = NULL;
        int i = 0;
        
        if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
        {
            LinkListNode* current = (LinkListNode*)sList;
            
            for(i=0; i<pos; i++)
            {
                current = current->next;
            }
            
            ret = current->next;
            current->next = ret->next;
            
            sList->length--;
        }
        
        return ret;
    }

    LinkList.h

    #ifndef _LINKLIST_H_
    #define _LINKLIST_H_
    
    typedef void LinkList;
    typedef struct _tag_LinkListNode LinkListNode;
    struct _tag_LinkListNode
    {
        LinkListNode* next;
    };
    
    LinkList* LinkList_Create();
    
    void LinkList_Destroy(LinkList* list);
    
    void LinkList_Clear(LinkList* list);
    
    int LinkList_Length(LinkList* list);
    
    int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
    
    LinkListNode* LinkList_Get(LinkList* list, int pos);
    
    LinkListNode* LinkList_Delete(LinkList* list, int pos);
    
    #endif

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "LinkList.h"
    
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    
    struct Value
    {
        LinkListNode header;
        int v;
    };
    
    int main(int argc, char *argv[]) 
    {
        int i = 0;
        LinkList* list = LinkList_Create();
        
        struct Value v1;
        struct Value v2;
        struct Value v3;
        struct Value v4;
        struct Value v5;
        
        v1.v = 1;
        v2.v = 2;
        v3.v = 3;
        v4.v = 4;
        v5.v = 5;
        
        //尾插法建立链表
         
        LinkList_Insert(list, (LinkListNode*)&v1, LinkList_Length(list));
        LinkList_Insert(list, (LinkListNode*)&v2, LinkList_Length(list));
        LinkList_Insert(list, (LinkListNode*)&v3, LinkList_Length(list));
        LinkList_Insert(list, (LinkListNode*)&v4, LinkList_Length(list));
        LinkList_Insert(list, (LinkListNode*)&v5, LinkList_Length(list));
        
        for(i=0; i<LinkList_Length(list); i++)
        {
            struct Value* pv = (struct Value*)LinkList_Get(list, i);
            
            printf("%d
    ", pv->v);
        }
        
        while( LinkList_Length(list) > 0 )
        {
            struct Value* pv = (struct Value*)LinkList_Delete(list, 0);
            
            printf("%d
    ", pv->v);
        }
        
        LinkList_Destroy(list);
        
        return 0;
    }

    优点:
      无需一次性定制链表的容量。
      插入和删除无需移动数据元素。

    缺点:
      数据元素必须保存后继元素的位置信息。
      获取指定的数据元素操作需要顺序访问之前的元素。

      单链表必须包含一个额外的指针域,没有指针的程序无法实现。(有些语言没有指针) 

    静态链表(单链表的数组方式实现)

    静态链表是顺序表的改进,解决了顺序表插入和删除要移动大量元素的问题,同时解决了单链表必须依靠指针的问题。

    静态链表(在顺序表的基础上用数组实现的单链表):

      顺序表中的元素由两个元素组成:data和next
      data用于存储数据。
      next用于存储下一个元素在数组中的下标。

    静态链表主要用于不支持指针的程序数据语言。

    静态链表的实现是一种内存管理的有简易方法。(类似 malloc, free功能)

    StaticList.h

    #ifndef _STATICLIST_H_
    #define _STATICLIST_H_
    
    typedef void StaticList;
    typedef void StaticListNode;
    
    StaticList* StaticList_Create(int capacity);
    
    void StaticList_Destroy(StaticList* list);
    
    void StaticList_Clear(StaticList* list);
    
    int StaticList_Length(StaticList* list);
    
    int StaticList_Capacity(StaticList* list);
    
    int StaticList_Insert(StaticList* list, StaticListNode* node, int pos);
    
    StaticListNode* StaticList_Get(StaticList* list, int pos);
    
    StaticListNode* StaticList_Delete(StaticList* list, int pos);
    
    #endif

    StaticList.c

    #include <stdio.h>
    #include <malloc.h>
    #include "StaticList.h"
    
    #define AVAILABLE -1
    
    typedef struct _tag_StaticListNode
    {
        unsigned int data;
        int next; //数组下标 
    } TStaticListNode;
    
    typedef struct _tag_StaticList
    {
        int capacity;
        TStaticListNode header; // 下面数组的第一个元素 
        TStaticListNode node[];
    } TStaticList;
    
    StaticList* StaticList_Create(int capacity) // O(n)
    {
        TStaticList* ret = NULL;
        int i = 0;
        
        if( capacity >= 0 )
        {
            ret = (TStaticList*)malloc(sizeof(TStaticList) + sizeof(TStaticListNode) * (capacity + 1));
        }
        
        if( ret != NULL )
        {
            ret->capacity = capacity;
            ret->header.data = 0; // length, 复用头结点  
            ret->header.next = 0; 
            
            for(i=1; i<=capacity; i++)
            {
                ret->node[i].next = AVAILABLE;
            }
        }
        
        return ret;
    }
    
    void StaticList_Destroy(StaticList* list) // O(1)
    {
        free(list);
    }
    
    void StaticList_Clear(StaticList* list) // O(n)
    {
        TStaticList* sList = (TStaticList*)list;
        int i = 0;
        
        if( sList != NULL )
        {
            sList->header.data = 0;
            sList->header.next = 0;
            
            for(i=1; i<=sList->capacity; i++)
            {
                sList->node[i].next = AVAILABLE;
            }
        }
    }
    
    int StaticList_Length(StaticList* list) // O(1)
    {
        TStaticList* sList = (TStaticList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->header.data;
        }
        
        return ret;
    }
    
    int StaticList_Capacity(StaticList* list) // O(1)
    {
        TStaticList* sList = (TStaticList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->capacity;
        }
        
        return ret;
    }
    
    int StaticList_Insert(StaticList* list, StaticListNode* node, int pos)  // O(n)
    {
        TStaticList* sList = (TStaticList*)list;
        int ret = (sList != NULL);
        int current = 0;
        int index = 0; // 可利用下标 
        int i = 0;
        
        ret = ret && (sList->header.data + 1 <= sList->capacity);
        ret = ret && (pos >=0) && (node != NULL);
        
        if( ret )
        {
            // 寻找可以利用的位置 
            for(i=1; i<=sList->capacity; i++)
            {
                if( sList->node[i].next == AVAILABLE )
                {
                    index = i;
                    break;
                }
            }
            
            sList->node[index].data = (unsigned int)node;
            
            sList->node[0] = sList->header;
            
            for(i=0; (i<pos) && (sList->node[current].next != 0); i++)
            {
                current = sList->node[current].next;
            }
            
            sList->node[index].next = sList->node[current].next;
            sList->node[current].next = index;
            
            sList->node[0].data++;
            
            sList->header = sList->node[0];
        }
        
        return ret;
    }
    
    StaticListNode* StaticList_Get(StaticList* list, int pos)  // O(n)
    {
        TStaticList* sList = (TStaticList*)list;
        StaticListNode* ret = NULL;
        int current = 0;
        int object = 0;
        int i = 0;
        
        if( (sList != NULL) && (0 <= pos) && (pos < sList->header.data) )
        {
            sList->node[0] = sList->header;
            
            for(i=0; i<pos; i++)
            {
                current = sList->node[current].next;
            }
            
            object = sList->node[current].next;
            
            ret = (StaticListNode*)(sList->node[object].data);
        }
        
        return ret;
    }
    
    StaticListNode* StaticList_Delete(StaticList* list, int pos) // O(n)
    {
        TStaticList* sList = (TStaticList*)list;
        StaticListNode* ret = NULL;
        int current = 0;
        int object = 0;
        int i = 0;
        
        if( (sList != NULL) && (0 <= pos) && (pos < sList->header.data) )
        {
            sList->node[0] = sList->header;
            
            for(i=0; i<pos; i++)
            {
                current = sList->node[current].next;
            }
            
            object = sList->node[current].next;
            
            sList->node[current].next = sList->node[object].next;
            
            sList->node[0].data--;
            
            sList->header = sList->node[0];
            
            sList->node[object].next = AVAILABLE;
            
            ret = (StaticListNode*)(sList->node[object].data);
        }
        
        return ret;
    }

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "StaticList.h"
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    
    int main(int argc, char *argv[])
    {
        StaticList* list = StaticList_Create(10);
        
        int index = 0;
        
        int i = 0;
        int j = 1;
        int k = 2;
        int x = 3;
        int y = 4;
        int z = 5;
        
        StaticList_Insert(list, &i, 0);
        StaticList_Insert(list, &j, 0);
        StaticList_Insert(list, &k, 0);
        
        for(index=0; index<StaticList_Length(list); index++)
        {
            int* p = (int*)StaticList_Get(list, index);
            
            printf("%d
    ", *p);
        }
        
        printf("
    ");
        
        while( StaticList_Length(list) > 0 )
        {
            int* p = (int*)StaticList_Delete(list, 0);
            
            printf("%d
    ", *p);
        }
        
        printf("
    ");
        
        StaticList_Insert(list, &x, 0);
        StaticList_Insert(list, &y, 0);
        StaticList_Insert(list, &z, 0);
        
        printf("Capacity: %d Length: %d
    ", StaticList_Capacity(list), StaticList_Length(list));
        
        for(index=0; index<StaticList_Length(list); index++)
        {
            int* p = (int*)StaticList_Get(list, index);
            
            printf("%d
    ", *p);
        }
        
        StaticList_Destroy(list);
        
        return 0;
    }

    循环链表(单链表的扩展)

    CircleList.h

    #ifndef _CIRCLELIST_H_
    #define _CIRCLELIST_H_
    
    typedef void CircleList;
    typedef struct _tag_CircleListNode CircleListNode;
    struct _tag_CircleListNode
    {
        CircleListNode* next;
    };
    
    CircleList* CircleList_Create();
    
    void CircleList_Destroy(CircleList* list);
    
    void CircleList_Clear(CircleList* list);
    
    int CircleList_Length(CircleList* list);
    
    int CircleList_Insert(CircleList* list, CircleListNode* node, int pos);
    
    CircleListNode* CircleList_Get(CircleList* list, int pos);
    
    CircleListNode* CircleList_Delete(CircleList* list, int pos);
    
    CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node);
    
    CircleListNode* CircleList_Reset(CircleList* list);
    
    CircleListNode* CircleList_Current(CircleList* list);
    
    CircleListNode* CircleList_Next(CircleList* list);
    
    #endif

    CircleList.c

    #include <stdio.h>
    #include <malloc.h>
    #include "CircleList.h"
    
    typedef struct _tag_CircleList
    {
        CircleListNode header;
        CircleListNode* slider; //游标 
        int length;
    } TCircleList;
    
    CircleList* CircleList_Create() // O(1)
    {
        TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList));
        
        if( ret != NULL )
        {
            ret->length = 0;
            ret->header.next = NULL;
            ret->slider = NULL;
        }
        
        return ret;
    }
    
    void CircleList_Destroy(CircleList* list) // O(1)
    {
        free(list);
    }
    
    void CircleList_Clear(CircleList* list) // O(1)
    {
        TCircleList* sList = (TCircleList*)list;
        
        if( sList != NULL )
        {
            sList->length = 0;
            sList->header.next = NULL;
            sList->slider = NULL;
        }
    }
    
    int CircleList_Length(CircleList* list) // O(1)
    {
        TCircleList* sList = (TCircleList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->length;
        }
        
        return ret;
    }
    
     
    int CircleList_Insert(CircleList* list, CircleListNode* node, int pos) // O(n) 注: n并非链表的长度,而是插入的位置 
    { 
        TCircleList* sList = (TCircleList*)list;
        int ret = (sList != NULL) && (pos >= 0) && (node != NULL);
        int i = 0;
        
        if( ret )
        {
            CircleListNode* current = (CircleListNode*)sList;
            
            for(i=0; (i<pos) && (current->next != NULL); i++)
            {
                current = current->next;
            }
            
            node->next = current->next;
            current->next = node;
            
            //特殊判断 构成环 
            if( sList->length == 0 )
            {
                sList->slider = node; // 游标默认指向第一个元素 
            }
            //特殊判断

     if( current == (CircleListNode*)sList )//如果插入的是第一个元素,尾节点要指向新插入的元素
     {
       CircleListNode* last = CircleList_Get(sList, sList->length - 1);
       last->next = current->next;
     }

            sList->length++;
        }
        
        return ret;
    }
    
    CircleListNode* CircleList_Get(CircleList* list, int pos) // O(n)
    {
        TCircleList* sList = (TCircleList*)list;
        CircleListNode* ret = NULL;
        int i = 0;
        
        if( (sList != NULL) && (pos >= 0) /*  可以转圈  */ )
        {
            CircleListNode* current = (CircleListNode*)sList;
            
            for(i=0; i<pos; i++)
            {
                current = current->next;
            }
            
            ret = current->next;
        }
        
        return ret;
    }
    
    CircleListNode* CircleList_Delete(CircleList* list, int pos) // O(n)
    {
        TCircleList* sList = (TCircleList*)list;
        CircleListNode* ret = NULL;
        int i = 0;
        
        if( (sList != NULL) && (pos >= 0)  && ( sList->length>0))
        {
            CircleListNode* current = (CircleListNode*)sList;
            CircleListNode* first = sList->header.next;
            CircleListNode* last = (CircleListNode*)CircleList_Get(sList, sList->length - 1);
            
            for(i=0; i<pos; i++)
            {
                current = current->next;
            }
            
            ret = current->next;
            current->next = ret->next;
            
            sList->length--;
            
            //删除首元素时 
            if( first == ret )
            {
               // sList->header.next = ret->next; // @todo 
                last->next = ret->next; // @oops 删除首元素时必须要手动处理环 
            }
            
            if( sList->slider == ret )
            {
                sList->slider = ret->next;
            }
    
            if( sList->length == 0 ) //@oops
            {
                sList->header.next = NULL; //链表变空时要手动 置为 null, 因为现在是环状,不会存在null值 
                sList->slider = NULL;
            }
        }
        
        return ret;
    }
    
    CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node) // O(n)
    {
        TCircleList* sList = (TCircleList*)list;
        CircleListNode* ret = NULL;
        int i = 0;
        
        if( sList != NULL )
        {
            CircleListNode* current = (CircleListNode*)sList;
            
            for(i=0; i<sList->length; i++)
            {
                if( current->next == node )
                {
                    ret = current->next;
                    break;
                }
                
                current = current->next;
            }
            
            if( ret != NULL )
            {
                CircleList_Delete(sList, i);
            }
        }
        
        return ret;
    }
    
    CircleListNode* CircleList_Reset(CircleList* list) // O(1)
    {
        TCircleList* sList = (TCircleList*)list;
        CircleListNode* ret = NULL;
        
        if( sList != NULL )
        {
            sList->slider = sList->header.next;
            ret = sList->slider;
        }
        
        return ret;
    }
    
    CircleListNode* CircleList_Current(CircleList* list) // O(1)
    {
        TCircleList* sList = (TCircleList*)list;
        CircleListNode* ret = NULL;
        
        if( sList != NULL )
        {
            ret = sList->slider;
        }
        
        return ret;
    }
    
    CircleListNode* CircleList_Next(CircleList* list) // O(1)
    {
        TCircleList* sList = (TCircleList*)list;
        CircleListNode* ret = NULL;
        
        if( (sList != NULL) && (sList->slider != NULL) )
        {
            ret = sList->slider;
            sList->slider = ret->next;
        }
        
        return ret;
    }

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "CircleList.h"
    
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    
    struct Value
    {
        CircleListNode header;
        int v;
    };
    
    int main(int argc, char *argv[])
    {
        int i = 0;
    
        CircleList* list = CircleList_Create();
        
        struct Value v1;
        struct Value v2;
        struct Value v3;
        struct Value v4;
        struct Value v5;
        struct Value v6;
        struct Value v7;
        struct Value v8;
        
        
        v1.v = 1;
        v2.v = 2;
        v3.v = 3;
        v4.v = 4;
        v5.v = 5;
        v6.v = 6;
        v7.v = 7;
        v8.v = 8;
        
        CircleList_Insert(list, (CircleListNode*)&v1, CircleList_Length(list));
        CircleList_Insert(list, (CircleListNode*)&v2, CircleList_Length(list));
        CircleList_Insert(list, (CircleListNode*)&v3, CircleList_Length(list));
        CircleList_Insert(list, (CircleListNode*)&v4, CircleList_Length(list));
        
        CircleList_Insert(list, (CircleListNode*)&v5, 5);
        CircleList_Delete(list, 0);
        
        for(i=0; i<2*CircleList_Length(list); i++)
        {
            struct Value* pv = (struct Value*)CircleList_Get(list, i);
            
            printf("%d
    ", pv->v);
        }
        
        printf("
    ");
        
        while( CircleList_Length(list) > 0 )
        {
            struct Value* pv = (struct Value*)CircleList_Delete(list, 0);
            
            printf("%d
    ", pv->v);
        }
        
       
       
        CircleList_Destroy(list);
        
        return 0;
    }

    循环链表是单链表基础上的一个增强,可以完全替代单链表。

    循环链表的next和current操作可以高效的遍历链表中的所有元素。

     双向链表:

    单链表的数据元素无法直接访问其前驱元素。
    逆序访问单链表的元素是极其耗时的。

    双向链表的定义:
      在单链表节点中增加一个指向其前驱的pre指针

    DLinkList.h

    #ifndef _DLINKLIST_H_
    #define _DLINKLIST_H_
    
    typedef void DLinkList;
    typedef struct _tag_DLinkListNode DLinkListNode;
    struct _tag_DLinkListNode
    {
        DLinkListNode* next;
        DLinkListNode* pre;
    };
    
    DLinkList* DLinkList_Create();
    
    void DLinkList_Destroy(DLinkList* list);
    
    void DLinkList_Clear(DLinkList* list);
    
    int DLinkList_Length(DLinkList* list);
    
    int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos);
    
    DLinkListNode* DLinkList_Get(DLinkList* list, int pos);
    
    DLinkListNode* DLinkList_Delete(DLinkList* list, int pos);
    
    DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);
    
    DLinkListNode* DLinkList_Reset(DLinkList* list);
    
    DLinkListNode* DLinkList_Current(DLinkList* list);
    
    DLinkListNode* DLinkList_Next(DLinkList* list);
    
    DLinkListNode* DLinkList_Pre(DLinkList* list);
    
    #endif

    DLinkList.c

    #include <stdio.h>
    #include <malloc.h>
    #include "DLinkList.h"
    
    typedef struct _tag_DLinkList
    {
        DLinkListNode header;
        DLinkListNode* slider;
        int length;
    } TDLinkList;
    
    DLinkList* DLinkList_Create() // O(1)
    {
        TDLinkList* ret = (TDLinkList*)malloc(sizeof(TDLinkList));
        
        if( ret != NULL )
        {
            ret->length = 0;
            ret->header.next = NULL;
            ret->header.pre = NULL;
            ret->slider = NULL;
        }
        
        return ret;
    }
    
    void DLinkList_Destroy(DLinkList* list) // O(1)
    {
        free(list);
    }
    
    void DLinkList_Clear(DLinkList* list) // O(1)
    {
        TDLinkList* sList = (TDLinkList*)list;
        
        if( sList != NULL )
        {
            sList->length = 0;
            sList->header.next = NULL;
            sList->header.pre = NULL;
            sList->slider = NULL;
        }
    }
    
    int DLinkList_Length(DLinkList* list) // O(1)
    {
        TDLinkList* sList = (TDLinkList*)list;
        int ret = -1;
        
        if( sList != NULL )
        {
            ret = sList->length;
        }
        
        return ret;
    }
    
    int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos) // O(n)
    { 
        TDLinkList* sList = (TDLinkList*)list;
        int ret = (sList != NULL) && (pos >= 0) && (node != NULL);
        int i = 0;
        
        if( ret )
        {
            DLinkListNode* current = (DLinkListNode*)sList;
            DLinkListNode* next = NULL;
            
            for(i=0; (i<pos) && (current->next != NULL); i++)
            {
                current = current->next;
            }
            
            next = current->next;
            
            current->next = node;
            node->next = next;
            
            //如果是空链表或最后一个元素则next没有prev 
            if( next != NULL )
            {
                next->pre = node;
            }
            
            node->pre = current;
            
            //如果插入的是第一个元素,prev应为 NULL 
            if( sList->length == 0 )
            {
                sList->slider = node; //游标默认指向第一个元素 
            }

    if( current == (CircleListNode*)sList )
    {
      CircleListNode* last = CircleList_Get(sList, sList->length - 1);
      last->next = current->next;
    }

            sList->length++;
        }
        
        return ret;
    }
    
    DLinkListNode* DLinkList_Get(DLinkList* list, int pos) // O(n)
    {
        TDLinkList* sList = (TDLinkList*)list;
        DLinkListNode* ret = NULL;
        int i = 0;
        
        if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
        {
            DLinkListNode* current = (DLinkListNode*)sList;
            
            for(i=0; i<pos; i++)
            {
                current = current->next;
            }
            
            ret = current->next;
        }
        
        return ret;
    }
    
    DLinkListNode* DLinkList_Delete(DLinkList* list, int pos) // O(n)
    {
        TDLinkList* sList = (TDLinkList*)list;
        DLinkListNode* ret = NULL;
        int i = 0;
        
        if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
        {
            DLinkListNode* current = (DLinkListNode*)sList;
            DLinkListNode* next = NULL;
            
            for(i=0; i<pos; i++)
            {
                current = current->next;
            }
            
            ret = current->next;
            next = ret->next;
            
            current->next = next;
            
            if( next != NULL )//删除最后一个元素 
            {
                next->pre = current;
                
                //删除第一个元素,第二元素的prev=null 
                if( current == (DLinkListNode*)sList )
                {
                    next->pre = NULL;
                }
            }
            
            if( sList->slider == ret )
            {
                sList->slider = next;
            }
            
            sList->length--;
        }
        
        return ret;
    }
    
    DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node)
    {
        TDLinkList* sList = (TDLinkList*)list;
        DLinkListNode* ret = NULL;
        int i = 0;
        
        if( sList != NULL )
        {
            DLinkListNode* current = (DLinkListNode*)sList;
            
            for(i=0; i<sList->length; i++)
            {
                if( current->next == node )
                {
                    ret = current->next;
                    break;
                }
                
                current = current->next;
            }
            
            if( ret != NULL )
            {
                DLinkList_Delete(sList, i);
            }
        }
        
        return ret;
    }
    
    DLinkListNode* DLinkList_Reset(DLinkList* list)
    {
        TDLinkList* sList = (TDLinkList*)list;
        DLinkListNode* ret = NULL;
        
        if( sList != NULL )
        {
            sList->slider = sList->header.next;
            ret = sList->slider;
        }
        
        return ret;
    }
    
    DLinkListNode* DLinkList_Current(DLinkList* list)
    {
        TDLinkList* sList = (TDLinkList*)list;
        DLinkListNode* ret = NULL;
        
        if( sList != NULL )
        {
            ret = sList->slider;
        }
        
        return ret;
    }
    
    DLinkListNode* DLinkList_Next(DLinkList* list)
    {
        TDLinkList* sList = (TDLinkList*)list;
        DLinkListNode* ret = NULL;
        
        if( (sList != NULL) && (sList->slider != NULL) )
        {
            ret = sList->slider;
            sList->slider = ret->next;
        }
        
        return ret;
    }
    
    DLinkListNode* DLinkList_Pre(DLinkList* list)
    {
        TDLinkList* sList = (TDLinkList*)list;
        DLinkListNode* ret = NULL;
        
        if( (sList != NULL) && (sList->slider != NULL) )
        {
            ret = sList->slider;
            sList->slider = ret->pre;
        }
        
        return ret;
    }

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "DLinkList.h"
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    
    struct Value
    {
        DLinkListNode header;
        int v;
    };
    
    int main(int argc, char *argv[])
    {
        int i = 0;
        DLinkList* list = DLinkList_Create();
        struct Value* pv = NULL;
        struct Value v1;
        struct Value v2;
        struct Value v3;
        struct Value v4;
        struct Value v5;
        
        v1.v = 1;
        v2.v = 2;
        v3.v = 3;
        v4.v = 4;
        v5.v = 5;
        
        DLinkList_Insert(list, (DLinkListNode*)&v1, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkListNode*)&v2, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkListNode*)&v3, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkListNode*)&v4, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkListNode*)&v5, DLinkList_Length(list));
        
        for(i=0; i<DLinkList_Length(list); i++)
        {
            pv = (struct Value*)DLinkList_Get(list, i);
            
            printf("%d
    ", pv->v);
        }
        
        printf("
    ");
        
        DLinkList_Delete(list, DLinkList_Length(list)-1);
        DLinkList_Delete(list, 0);
        
        for(i=0; i<DLinkList_Length(list); i++)
        {
            pv = (struct Value*)DLinkList_Next(list);
            
            printf("%d
    ", pv->v);
        }
        
        printf("
    ");
        
        DLinkList_Reset(list);
        DLinkList_Next(list);
        
        pv = (struct Value*)DLinkList_Current(list);
        
        printf("%d
    ", pv->v);
        
        DLinkList_DeleteNode(list, (DLinkListNode*)pv);
        
        pv = (struct Value*)DLinkList_Current(list);
        
        printf("%d
    ", pv->v);
        
        DLinkList_Pre(list);
        
        pv = (struct Value*)DLinkList_Current(list);
        
        printf("%d
    ", pv->v);
        
        printf("Length: %d
    ", DLinkList_Length(list));
        
        DLinkList_Destroy(list);
        
        return 0;
    }
  • 相关阅读:
    QT QQuickView嵌入到QT MDI中
    地理入门-经纬度时区速成总结篇(转)
    Linux下系统时间函数、DST等相关问题总结(转)
    camera接口---MIPI CSI-2接口、DVP接口和FPD-Link III LVDS、GMSL等接口对比(转)
    基于spi FLASH的嵌入式文件系统 littlefs(转)
    PID 温控系统 解决方法(转)
    单相计量芯片RN8209D使用经验分享(转)
    【开源】EasyFlash 新年发布 V4.0 beta 版,完全重写(转)
    在uboot中加入cmd_run命令,运行环境变量(转)
    MPU6050开发 -- 数据分析(转)
  • 原文地址:https://www.cnblogs.com/siqi/p/4771448.html
Copyright © 2011-2022 走看看