C语言实现双向非循环链表(带头结点尾结点)的基本操作

来源:互联网 发布:如何防范网络黑客攻击 编辑:程序博客网 时间:2024/04/30 06:09

       我在之前一篇博客中《C语言实现双向非循环链表(不带头结点)的基本操作》中详细实现了不带头尾节点的双向非循环链表的很多操作。其实同单链表一样,不带头结点的链表很多操作都是比较麻烦的,常常需要对第一个节点做额外的判断,提高了出错的成本。今天我们要来实现带头结点尾结点的双向非循环链表的操作,虽然额外维护了两个节点,但是操作的简便性大大提高了。代码上传至 https://github.com/chenyufeng1991/DoubleLinkedList_HeadList  。

(1)定义带头结点尾结点的非循环双向链表的节点类型

typedef int elemType;typedef struct NodeList{    int element;    struct NodeList *prior;    struct NodeList *next;}Node;

(2)初始化双链表

//1.初始化带头结点和尾结点的非循环双向链表void InitialList(Node **pHead,Node **pTail){    *pHead = (Node *)malloc(sizeof(Node));    *pTail = (Node *)malloc(sizeof(Node));    if (*pHead == NULL || *pTail == NULL) {        printf("%s函数执行,内存分配失败,初始化双链表失败\n",__FUNCTION__);    }else{        //这个里面是关键,也是判空的重要条件        (*pHead)->prior = NULL;        (*pTail)->next = NULL;        //链表为空的时候把头结点和尾结点连起来        (*pHead)->next = *pTail;        (*pTail)->prior = *pHead;        printf("%s函数执行,带头结点和尾节点的双向非循环链表初始化成功\n",__FUNCTION__);    }}

(3)尾插法创建双链表

//2.创建带头结点和尾结点的双向非循环链表void CreateList(Node *pHead,Node *pTail){    Node *pInsert;    Node *pMove;    pInsert = (Node*)malloc(sizeof(Node));    memset(pInsert, 0, sizeof(Node));    pInsert->prior = NULL;    pInsert->next = NULL;    scanf("%d",&(pInsert->element));    pMove = pHead;    while (pInsert->element > 0) {        pMove->next = pInsert;        pInsert->prior = pMove;        pInsert->next = pTail;        pTail->prior = pInsert;        pMove = pInsert;        pInsert = (Node *)malloc(sizeof(Node));        memset(pInsert, 0, sizeof(Node));        pInsert->prior = NULL;        pInsert->next = NULL;        scanf("%d",&(pInsert->element));    }    printf("%s函数执行完成,带头节点和尾结点的双向非循环链表创建成功\n",__FUNCTION__);}

(4)正序打印链表

//3.正序打印链表void PrintList(Node *pHead,Node *pTail){    Node *pMove;    pMove = pHead->next;    while (pMove != pTail) {        printf("%d ",pMove->element);        pMove = pMove->next;    }    printf("\n%s函数执行,正序打印带头结点尾结点的双向非循环链表创建成功\n",__FUNCTION__);}


(5)逆序打印链表

//4.逆序打印链表void PrintReverseList(Node *pHead,Node *pTail){    Node *pMove;    pMove = pTail->prior;    while (pMove != pHead) {        printf("%d ",pMove->element);        pMove = pMove->prior;    }    printf("\n%s函数执行,逆序打印带头结点尾结点的双向非循环链表创建成功\n",__FUNCTION__);}

(6)清空节点,使成为空表

//5.清除链表中的所有元素,使成为空表void ClearList(Node *pHead,Node *pTail){    Node *pMove;    pMove = pHead->next;    while (pMove != pTail) {        pHead->next = pMove->next;        pMove->next->prior = pHead;        free(pMove);        pMove = pHead->next;    }    printf("%s函数执行,双向非循环链表清空成功\n",__FUNCTION__);}

(7)计算链表长度

//6.计算链表的长度int SizeList(Node *pHead,Node *pTail){    int i = 0;    Node *pMove;    pMove = pHead->next;    while (pMove != pTail) {        i++;        pMove = pMove->next;    }    printf("%s函数执行,链表的长度为%d\n",__FUNCTION__,i);    return i;}

(8)判断链表是否为空

//7.判断带头结点尾结点的双向非循环链表是否为空,为空返回1,否则返回0int IsEmptyList(Node *pHead,Node *pTail){    if (pHead->next == pTail) {        printf("%s函数执行,当前链表为空\n",__FUNCTION__);        return 1;    }    printf("%s函数执行,当前链表不为空\n",__FUNCTION__);    return 0;}

(9)返回链表中pos位置的元素

//8.返回链表中第pos个结点中的元素,若返回-1,表示没有找到int GetElement(Node *pHead,Node *pTail,int pos){    int i = 1;    Node *pMove;    pMove = pHead->next;    while (pMove != pTail) {        if (i == pos) {            printf("%s函数执行,第pos=%d位置的元素为%d\n",__FUNCTION__,pos,pMove->element);            return pMove->element;        }        i++;        pMove = pMove->next;    }    printf("%s函数执行,查找第pos=%d位置元素失败\n",__FUNCTION__,pos);    return -1;}

(10)查找值为x的节点,如果存在则返回地址

//9.从链表中查找给定值x的第一个元素,并返回data域的内存地址,否则返回NULLint *GetElemAddr(Node *pHead,Node *pTail,int x){    Node *pMove;    pMove = pHead->next;    while (pMove != pTail) {        if (pMove->element == x) {            printf("%s函数执行,值为%d的元素内存地址为0x%x\n",__FUNCTION__,x,&(pMove->element));            return &(pMove->element);        }        pMove = pMove->next;    }    printf("%s函数执行,查找值为%d的元素地址失败\n",__FUNCTION__,x);    return NULL;}

(11)把pos节点的值改为x

//10.把链表中第pos个节点的值修改为xint ModifyElem(Node *pHead,Node *pTail,int pos,int x){    int i = 1;    Node *pMove;    pMove = pHead->next;    while (pMove != pTail) {        if (i == pos) {            pMove->element = x;            printf("%s函数执行,修改pos=%d位置值为%d成功\n",__FUNCTION__,pos,x);            return 1;        }        i++;        pMove = pMove->next;    }    printf("%s函数执行,修改pos=%d位置元素失败\n",__FUNCTION__,pos);    return -1;}

(12)表头插入一个元素

//11.向链表的表头插入一个元素int InsertHeadList(Node *pHead,Node *pTail,int x){    Node *pInsert;    pInsert = (Node *)malloc(sizeof(Node));    memset(pInsert, 0, sizeof(Node));    pInsert->element = x;    pInsert->prior = NULL;    pInsert->next = NULL;    pInsert->next = pHead->next;    pHead->next->prior = pInsert;    pHead->next = pInsert;    pInsert->prior = pHead;    printf("%s函数执行,在表头插入%d成功\n",__FUNCTION__,x);    return 1;}

(13)表尾插入一个元素

//12.向链表的表尾插入一个元素int InsertTailList(Node *pHead,Node *pTail,int x){    Node *pInsert;    pInsert = (Node *)malloc(sizeof(Node));    memset(pInsert, 0, sizeof(Node));    pInsert->element = x;    pInsert->prior = NULL;    pInsert->next = NULL;    pTail->prior->next = pInsert;    pInsert->prior = pTail->prior;    pInsert->next = pTail;    pTail->prior = pInsert;    printf("%s函数执行,在表尾插入%d成功\n",__FUNCTION__,x);    return 1;}

(14)测试代码

int main(int argc, const char * argv[]) {    Node *pHead;//头结点    Node *pTail;//尾结点    InitialList(&pHead, &pTail);    CreateList(pHead, pTail);    PrintList(pHead, pTail);    PrintReverseList(pHead,pTail);    SizeList(pHead, pTail);    IsEmptyList(pHead,pTail);    GetElement(pHead, pTail, 2);    GetElemAddr(pHead, pTail, 5);    ModifyElem(pHead, pTail, 2, 111);    PrintList(pHead, pTail);        InsertHeadList(pHead,pTail,100);    PrintList(pHead, pTail);    InsertTailList(pHead,pTail,900);    PrintList(pHead, pTail);        ClearList(pHead,pTail);    PrintList(pHead, pTail);    IsEmptyList(pHead,pTail);        return 0;}


1 0
原创粉丝点击