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

来源:互联网 发布:淘宝直通车设置流程 编辑:程序博客网 时间:2024/05/16 01:12

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

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

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

代码如下:

Dlist.h

#ifndef DList_H#define DList_Htypedef  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前驱位置的值为%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");}

执行结果如下:


0 0