您的位置:首页 > 编程语言 > C语言/C++

C语言一个双向链表的实现

2013-08-07 21:19 447 查看
首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下:
#ifndef DList_H  
#define DList_H  
typedef  int Item;  
typedef struct Node * PNode;  
typedef PNode Position;  
/*定义节点类型*/ 
typedef struct Node  
{  
    Item data;      /*数据域*/ 
    PNode previous; /*指向前驱*/ 
    PNode next;     /*指向后继*/ 
}Node;  
/*定义链表类型*/ 
typedef struct 
{  
    PNode head;     /*指向头节点*/ 
    PNode tail;     /*指向尾节点*/ 
    int size;  
}DList;  
   
/*分配值为i的节点,并返回节点地址*/ 
Position MakeNode(Item i);  
   
/*释放p所指的节点*/ 
void FreeNode(PNode p);  
   
/*构造一个空的双向链表*/ 
DList* InitList();  
   
/*摧毁一个双向链表*/ 
void DestroyList(DList *plist);  
   
/*将一个链表置为空表,释放原链表节点空间*/ 
void ClearList(DList *plist);  
   
/*返回头节点地址*/ 
Position GetHead(DList *plist);  
   
/*返回尾节点地址*/ 
Position GetTail(DList *plist);  
   
/*返回链表大小*/ 
int GetSize(DList *plist);  
   
/*返回p的直接后继位置*/ 
Position GetNext(Position p);  
   
/*返回p的直接前驱位置*/ 
Position GetPrevious(Position p);  
   
/*将pnode所指节点插入第一个节点之前*/ 
PNode InsFirst(DList *plist,PNode pnode);  
   
/*将链表第一个节点删除并返回其地址*/ 
PNode DelFirst(DList *plist);  
   
/*获得节点的数据项*/ 
Item GetItem(Position p);  
   
/*设置节点的数据项*/ 
void SetItem(Position p,Item i);  
   
/*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/ 
PNode Remove(DList *plist);  
   
/*在链表中p位置之前插入新节点S*/ 
PNode InsBefore(DList *plist,Position p,PNode s);  
   
/*在链表中p位置之后插入新节点s*/ 
PNode InsAfter(DList *plist,Position p,PNode s);  
   
/*返回在链表中第i个节点的位置*/ 
PNode LocatePos(DList *plist,int i);  
   
/*依次对链表中每个元素调用函数visit()*/ 
void ListTraverse(DList *plist,void (*visit)());  
#endif


接下来逐个实现其功能,DList.c内容如下:
#include"DList.h"  
#include<malloc.h>  
#include<stdlib.h>  
/*分配值为i的节点,并返回节点地址*/ 
Position MakeNode(Item i)  
{  
    PNode p = NULL;   
    p = (PNode)malloc(sizeof(Node));  
    if(p!=NULL)  
    {  
        p->data = i;  
        p->previous = NULL;  
        p->next = NULL;  
    }     
    return p;  
}  
/*释放p所指的节点*/ 
void FreeNode(PNode p)  
{  
     free(p);  
}  
/*构造一个空的双向链表*/ 
DList * InitList()  
{  
    DList *plist = (DList *)malloc(sizeof(DList));  
    PNode head = MakeNode(0);   
    if(plist!=NULL)  
    {  
        if(head!=NULL)  
        {  
            plist->head = head;  
            plist->tail = head;  
            plist->size = 0;  
        }  
        else 
            return NULL;  
    }  
    return plist;  
}  
   
/*摧毁一个双向链表*/ 
void DestroyList(DList *plist)  
{  
    ClearList(plist);  
    free(GetHead(plist));  
    free(plist);  
}  
   
/*判断链表是否为空表*/ 
int IsEmpty(DList *plist)  
{  
    if(GetSize(plist)==0&&GetTail(plist)==GetHead(plist))  
        return 1;  
    else 
        return 0;  
}  
/*将一个链表置为空表,释放原链表节点空间*/ 
void ClearList(DList *plist)  
{  
    PNode temp,p;  
    p = GetTail(plist);  
    while(!IsEmpty(plist))  
    {     
        temp = GetPrevious(p);  
        FreeNode(p);  
        p = temp;  
        plist->tail = temp;  
        plist->size--;  
    }  
}  
   
/*返回头节点地址*/ 
Position GetHead(DList *plist)  
{  
    return plist->head;  
}  
   
/*返回尾节点地址*/ 
Position GetTail(DList *plist)  
{  
    return plist->tail;  
}  
   
/*返回链表大小*/ 
int GetSize(DList *plist)  
{  
    return plist->size;  
}  
   
/*返回p的直接后继位置*/ 
Position GetNext(Position p)  
{  
    return p->next;  
}  
   
/*返回p的直接前驱位置*/ 
Position GetPrevious(Position p)  
{  
    return p->previous;  
}  
   
/*将pnode所指节点插入第一个节点之前*/ 
PNode InsFirst(DList *plist,PNode pnode)  
{  
    Position head = GetHead(plist);  
   
    if(IsEmpty(plist))  
        plist->tail = pnode;  
    plist->size++;  
   
    pnode->next = head->next;  
    pnode->previous = head;  
   
    if(head->next!=NULL)  
        head->next->previous = pnode;  
    head->next = pnode;  
       
    return pnode;   
}  
   
/*将链表第一个节点删除,返回该节点的地址*/ 
PNode DelFirst(DList *plist)  
{  
    Position head = GetHead(plist);  
    Position p=head->next;  
    if(p!=NULL)  
    {  
        if(p==GetTail(plist))  
            plist->tail = p->previous;  
        head->next = p->next;  
        head->next->previous = head;  
        plist->size--;  
           
    }     
    return p;  
}  
   
/*获得节点的数据项*/ 
Item GetItem(Position p)  
{  
    return p->data;  
}  
   
/*设置节点的数据项*/ 
void SetItem(Position p,Item i)  
{  
    p->data = i;  
}  
   
/*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/ 
PNode Remove(DList *plist)  
{  
    Position p=NULL;  
    if(IsEmpty(plist))  
        return NULL;  
    else 
    {  
        p = GetTail(plist);  
        p->previous->next = p->next;  
        plist->tail = p->previous;  
        plist->size--;  
        return p;  
    }  
}  
/*在链表中p位置之前插入新节点s*/ 
PNode InsBefore(DList *plist,Position p,PNode s)  
{  
    s->previous = p->previous;  
    s->next = p;  
    p->previous->next = s;      
    p->previous = s;  
   
    plist->size++;  
    return s;  
}  
/*在链表中p位置之后插入新节点s*/ 
PNode InsAfter(DList *plist,Position p,PNode s)  
{  
    s->next = p->next;  
    s->previous = p;  
       
    if(p->next != NULL)  
        p->next->previous = s;  
    p->next = s;  
       
    if(p = GetTail(plist))  
        plist->tail = s;  
       
    plist->size++;  
    return s;  
}  
   
/*返回在链表中第i个节点的位置*/ 
PNode LocatePos(DList *plist,int i)  
{  
    int cnt = 0;  
    Position p = GetHead(plist);  
    if(i>GetSize(plist)||i<1)  
        return NULL;  
   
    while(++cnt<=i)  
    {  
        p=p->next;  
    }  
   
    return p;  
}  
   
/*依次对链表中每个元素调用函数visit()*/ 
void ListTraverse(DList *plist,void (*visit)())  
{  
    Position p = GetHead(plist);  
    if(IsEmpty(plist))  
        exit(0);  
    else 
    {  
           
        while(p->next!=NULL)  
        {  
            p = p->next;  
            visit(p->data);            
        }         
    }  
}


接下来进行测试,Test.c内容如下:

#include"DList.h"  
#include<stdio.h>  
void print(Item i)  
{  
    printf("数据项为%d n",i);  
}  
main()  
{  
    DList *plist = NULL;  
    PNode p = NULL;  
       
    plist = InitList();  
    p = InsFirst(plist,MakeNode(1));  
    InsBefore(plist,p,MakeNode(2));  
    InsAfter(plist,p,MakeNode(3));  
   
    printf("p前驱位置的值为%dn",GetItem(GetPrevious(p)));  
    printf("p位置的值为%dn",GetItem(p));  
    printf("p后继位置的值为%dn",GetItem(GetNext(p)));  
       
       
    printf("遍历输出各节点数据项:n");  
    ListTraverse(plist,print);  
    printf("除了头节点该链表共有%d个节点n",GetSize(plist));  
    FreeNode(DelFirst(plist));  
    printf("删除第一个节点后重新遍历输出为:n");  
    ListTraverse(plist,print);  
    printf("除了头节点该链表共有%d个节点n",GetSize(plist));  
    DestroyList(plist);  
    printf("链表已被销毁n");  
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: