Linux c 算法与数据结构--双向链表

最近一直在巩固C语言基础,写的一些文章主要也是当自己的学习笔记,肯定会出现一些小错误,或者内容比较初级,希望通过自己的努力写出一些高水平的博文!

链表是linux c中非常重要的数据结构,双向链表与单向链表的区别,是它每个节点有两个指针域,分别指向该节点的前一个节点与后一个节点;

而链表的操作主要是查询、插入、删除、遍历等,下面来看一个双向链表,主要是进行写小练习,加深印象!

代码如下:

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
#include
/*分配值为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
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前驱位置的值为%d\n",GetItem(GetPrevious(p)));
    printf("p位置的值为%d\n",GetItem(p));
    printf("p后继位置的值为%d\n",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");
}

执行结果如下:


你可能感兴趣的:(数据结构与算法)