zoukankan      html  css  js  c++  java
  • 数据结构 线性双向链表

    //线性双向链表
    #ifndef _MY_DLINKLIST_H_
    #define _MY_DLINKLIST_H_
    
    typedef void DLinkList;
    
    typedef struct _tag_DLinkListNode
    {
        struct _tag_DLinkListNode* next;
        struct _tag_DLinkListNode * pre;
    }DLinkListNode;
    
    //创建双向链表
    DLinkList* DLinkList_Create();
    
    //销毁双向链表
    int DLinkList_Destroy(DLinkList ** list);
    
    //清空双向链表
    int 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);
    
    //-- add
    //删除双线链表的一个节点
    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
    //线性双向链表代码实现
    
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include"dlinklist.h"
    
    /*
    双向链表
    第0个节点没有前驱,最后一个节点没有后继
    */
    
    typedef struct _TDlinkList{
        //定义头结点
        DLinkListNode node;
        //定义游标
        DLinkListNode * slider;
        //定义链表长度
        int length;
    }TDlinkList;
    
    //创建双向链表
    _declspec(dllexport)
    DLinkList * DLinkList_Create(){
        TDlinkList * tlist = (TDlinkList *)malloc(sizeof(TDlinkList));
        if (tlist==NULL)
        {
            printf("分配内存失败!
    ");
            return NULL;
        }
        //初始化双向链表结构体参数
        tlist->length = 0;
        tlist->node.pre = NULL;
        tlist->node.next = NULL;
        tlist->slider = NULL;
        return (DLinkList *)tlist;
    }
    
    //销毁链表
    _declspec(dllexport)
    int DLinkList_Destroy(DLinkList ** list){
        int ERRO_MSG = 0;
        if (list==NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        TDlinkList * tlist = (TDlinkList *)*list;
        if (tlist!=NULL)
        {
            free(tlist);
            tlist = NULL;
            *list = NULL;
        }
        return ERRO_MSG;
    }
    
    //清空双向链表
    _declspec(dllexport)
    int DLinkList_Clear(DLinkList* list){
        int ERRO_MSG = 0;
        if (list == NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        tlist->length = 0;
        tlist->slider = NULL;
        tlist->node.pre = NULL;
        tlist->node.next = NULL;
        return ERRO_MSG;
    }
    
    //获取双向链表长度
    _declspec(dllexport)
    int DLinkList_Length(DLinkList* list){
        int ERRO_MSG = 0;
        if (list == NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        return tlist->length;
    }
    
    //双向链表指定位置插入元素
    _declspec(dllexport)
    int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos){
        int ERRO_MSG = 0,i=0;
        if (list == NULL || node==NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        //位置判断
        if (pos<0 || pos>tlist->length)
        {
            //进行容错处理
            pos = tlist->length;
        }
        //定义两个变量 
        DLinkListNode * pPrior = &tlist->node, *pCurrent = tlist->node.next;
        //普通情况实现
        //遍历链表
        for (i = 0; i < pos ; i++)
        {
            //变量后移
            pPrior = pCurrent;
            pCurrent = pCurrent->next;
        }
        node->next = pCurrent;
        pPrior->next = node;
        if (pCurrent!=NULL)
        {
            pCurrent->pre = node;
            
        }
        node->pre = pPrior;
        //判断是不是第0个节点
        if (pPrior == &tlist->node)
        {
            node->pre = NULL;
        }
        //游标指向第0个节点
        if (tlist->length==0)
        {
            tlist->slider = node;
        }
    
        //双向链表个数+1
        tlist->length++;
    
        /*
            特殊情况处理
            ①:第0个位置插入--下一个节点没问题 但是前一个节点必须是NULL
            if (pPrior == &tlist->node)
            {
                node->pre = NULL;
            }
            ②:原来是个空链表  此时pCurrent=NULL  
                node->next = pCurrent;执行没有问题
                pPrior->next = node;执行没有问题
                pCurrent->pre = node;执行报错  pCurrent为NULL  无法对内存0位置赋值  修正  加上非空判断
                if (pCurrent!=NULL)
                {
                    pCurrent->pre = node;
                }
                node->pre = pPrior;执行逻辑有问题  此时第0个元素没有前驱节点  修正
                if (pPrior == &tlist->node)
                {
                    node->pre = NULL;
                }
                else{
                    node->pre = pPrior;
                }
                ③:在末尾插入节点  上述逻辑已经满足条件
        */
    
    
        return ERRO_MSG;
    }
    
    //获取双向链表指定位置的元素
    _declspec(dllexport)
    DLinkListNode* DLinkList_Get(DLinkList* list, int pos){
        int ERRO_MSG = 0, i = 0;
        if (list == NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        //位置判断
        if (pos<0 || pos>tlist->length)
        {
            ERRO_MSG = -2;
            printf("该位置没有元素!
    ", ERRO_MSG);
            return NULL;
        }
        DLinkListNode * current = tlist->node.next;
        for (i = 0; i < pos; i++)
        {
            current = current->next;
        }
        return current;
    
    }
    
    //删除双向链表指定位置的元素
    _declspec(dllexport)
    DLinkListNode* DLinkList_Delete(DLinkList* list, int pos){
        int ERRO_MSG = 0, i = 0;
        if (list == NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        //位置判断
        if (pos<0 || pos>tlist->length)
        {
            ERRO_MSG = -2;
            printf("该位置没有元素!
    ", ERRO_MSG);
            return NULL;
        }
        //普通情况处理
        //定义两个变量 
        DLinkListNode * pPrior = &tlist->node, *pCurrent = tlist->node.next,*pNext=NULL;
        for (i = 0; i < pos; i++)
        {
            pPrior = pCurrent;
            pCurrent = pCurrent->next;
        }
        pNext = pCurrent->next;
        pPrior->next = pNext;
        if (pNext!=NULL)
        {
            pNext->pre = pPrior;
            //判断删除的是否是第0个元素
            if (pPrior == &tlist->node)
            {
                pNext->pre = NULL;
            }
        }
        /*
          特殊情况处理
          ①:删除第0个元素
              pNext = pCurrent->next; 正确   pNext指向下一个元素
              pPrior->next = pNext; 正确  头结点指向下一个节点
              if (pNext!=NULL)
              {
                 pNext->pre = pPrior;
              }  错误  此时 下一个节点的上一个节点应该指向NULL
              所以  应该追加对第0个元素的处理
              if (pPrior == &tlist->node)
              {
                   pNext->pre = NULL;
              }
    
          ②:只有一个元素删除
              pNext = pCurrent->next; 正确 此时 pNext=NULL
              pPrior->next = pNext; 正确 头结点指向NULL
              pNext->pre = pPrior;  错误  此时pNext为NULL  不可以赋值  修正
              if (pNext!=NULL)
              {
              pNext->pre = pPrior;
              }
          ③:删除最后一个元素
             pNext = pCurrent->next; 正确  此时pNext=NULL
             pPrior->next = pNext;  正确
             if (pNext!=NULL)
             {
                 pNext->pre = pPrior;
                 //判断删除的是否是第0个元素
                 if (pPrior == &tlist->node)
                 {
                     pNext->pre = NULL;
                 }
             }
             正确 pNext=NULL  此时应该不作处理
        */
        return pCurrent;
    
    }
    
    //删除双线链表的一个节点
    _declspec(dllexport)
    DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node){
        int ERRO_MSG = 0, i = 0;
        if (list == NULL || node==NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        DLinkListNode * pCurrent = &tlist->node;
        for (i = 0; i < tlist->length; i++)
        {
            pCurrent = pCurrent->next;
            if (pCurrent == node)
            {
                break;
            }
        }
        return DLinkList_Delete(list, i);
    }
    
    //游标重置
    _declspec(dllexport)
    DLinkListNode* DLinkList_Reset(DLinkList* list){
        int ERRO_MSG = 0;
        if (list == NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        tlist->slider = tlist->node.next;
        return tlist->slider;
    }
    
    //获取当前游标
    _declspec(dllexport)
    DLinkListNode* DLinkList_Current(DLinkList* list){
        int ERRO_MSG = 0;
        if (list == NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        return tlist->slider;
    }
    
    //游标后移 返回下一个位置的元素
    _declspec(dllexport)
    DLinkListNode* DLinkList_Next(DLinkList* list){
        int ERRO_MSG = 0;
        if (list == NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        if (tlist->slider==NULL)
        {
            ERRO_MSG = -2;
            printf("游标不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        tlist->slider = tlist->slider->next;
        return tlist->slider;
    }
    
    //游标前移 返回上一个位置的元素
    _declspec(dllexport)
    DLinkListNode* DLinkList_Pre(DLinkList* list){
        int ERRO_MSG = 0;
        if (list == NULL)
        {
            ERRO_MSG = -1;
            printf("传入参数不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        TDlinkList * tlist = (TDlinkList *)list;
        if (tlist->slider == NULL)
        {
            ERRO_MSG = -2;
            printf("游标不可以为空!
    ", ERRO_MSG);
            return NULL;
        }
        tlist->slider = tlist->slider->pre;
        return tlist->slider;
    }
    //线性双向链表测试代码
    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include"dlinklist.h"
    
    typedef struct _Student{
        //必须加一个DLinkListNode节点
        DLinkListNode node;
        char name[30];
        int age;
    }Student;
    
    void Test(){
        Student s1, s2, s3, s4, s5, s6, s7, s8;
        int numx = 0, i = 0, ret = 0;
        strcpy(s1.name, "小米");
        s1.age = 11;
        strcpy(s2.name, "小刚");
        s2.age = 12;
        strcpy(s3.name, "小红");
        s3.age = 10;
        strcpy(s4.name, "啸天");
        s4.age = 13;
        strcpy(s5.name, "莲华");
        s5.age = 12;
        s4.age = 13;
        strcpy(s6.name, "夏利");
        s6.age = 11;
        strcpy(s7.name, "小李");
        s7.age = 13;
        strcpy(s8.name, "阿凯");
        s8.age = 12;
        //线性表指针
        DLinkList *list = NULL;
        //创建线性链表
        list = DLinkList_Create();
        //插入元素
        DLinkList_Insert(list, (DLinkList *)&s1, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkList *)&s2, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkList *)&s3, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkList *)&s4, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkList *)&s5, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkList *)&s6, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkList *)&s7, DLinkList_Length(list));
        DLinkList_Insert(list, (DLinkList *)&s8, DLinkList_Length(list));
        //获取元素个数
        numx = DLinkList_Length(list);
        //逆序打印元素--游标的使用
        //重置游标
        Student *temp = (Student *)DLinkList_Reset(list);
        while (--numx)
        {
            temp = (Student *)DLinkList_Next(list);
        }
        while (temp != NULL){
            printf("我的名字是%s;我的年龄是%d
    ", temp->name, temp->age);
            temp = (Student *)DLinkList_Pre(list);
        }
        //删除线性表中的数据
        Student *delem = (Student *)DLinkList_Delete(list, 2);
        printf("我被删除了,我的名字是%s;我的年龄是%d
    ", delem->name, delem->age);
        //销毁线性表
        ret = DLinkList_Destroy(&list);
        if (ret == 0)printf("线性双向链表销毁成功!
    ");
    }
    
    void main(){
        Test();
        system("pause");
    }

     

  • 相关阅读:
    《党务管理信息系统的设计与实现》论文笔记(八)
    《高校党务信息系统的研究与分析》论文笔记(七)
    《用分布式多层应用技术开发党务管理信息系统》论文笔记(六)
    《二级学院《党务管理信息系统》的使用管理》论文笔记(五)
    《某学院党务管理信息系统的研究与设计》论文笔记(四)
    《数据结构课程现代教学中基于Web题库管理系统设计与实现》论文笔记(十)
    《课程管理系统的设计与实现》论文笔记(九)
    《基于微信平台的课程管理系统设计》论文笔记(八)
    《基于SSH框架的课程管理系统的设计与实现》论文笔记(七)
    《基于Android平台的大学生课程计划管理系统》论文笔记(六)
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/5689711.html
Copyright © 2011-2022 走看看