C语言实现双向链表:操作与源代码解析

需积分: 9 1 下载量 97 浏览量 更新于2024-09-14 收藏 52KB DOC 举报
"本文介绍了如何用C语言实现双向链表,包括创建、打印、销毁链表、获取链表长度、获取指定位置元素、插入新节点以及删除指定位置节点等操作。" 在计算机科学中,数据结构是组织和管理数据的重要工具,而链表是一种常用的数据结构。双向链表(Doubly Linked List)是链表的一种变体,每个节点不仅包含数据,还包含指向下一个节点的指针,以及一个指向前一个节点的指针,从而可以双向遍历链表。 `DNode` 结构体定义了双向链表的节点: ```c typedef struct DNode { char data; // 节点数据,这里以字符类型为例 struct DNode *prior, *next; // 分别指向前一个节点和后一个节点的指针 } DNode, *DLinkList; // DLinkList 是指向DNode类型的指针,用作链表的头指针 ``` 接下来,我们分析提供的部分代码实现的关键功能: 1. **创建双向链表**: `DNode* CreateDLinkList(DNode* L)`:这个函数用于初始化空的双向链表。通常,它会返回一个指向新创建的头节点的指针。 2. **打印双向链表**: `void DLinkPrint(DNode* L)`:此函数遍历整个链表,依次打印每个节点的数据,用于查看链表的内容。 3. **销毁双向链表**: `void DestroyDLinkList(DNode* L)`:该函数释放链表中所有节点的内存,确保不再有内存泄漏。需要注意在释放节点时,需要同时更新指针,防止悬挂指针。 4. **获取链表长度**: `int GetLengthFromDLinkList(DNode* L)`:计算链表的长度,即遍历链表并计数的过程。 5. **获取双线性链表的第i个元素**: `DNode* GetElemFromDLinkList(DNode* L, int i)`:根据索引i返回链表中的第i个元素。需要检查索引是否有效,以及链表是否为空。 6. **在双线性链表的第i个位置插入新结点**: `int DLinkListInsert(DNode* L, int i, char elem)`:在链表的第i个位置插入值为elem的新节点。插入操作需要更新前后节点的指针,并且处理边界条件,例如当i为0时插入到链表头部,i等于链表长度时插入到尾部。 7. **删除双向链表中的第i个结点**: `int DLinkListDelete(DNode* L, int i, char* elem)`:删除链表中的第i个节点,同时返回被删除节点的数据。同样需要处理边界条件和正确更新指针。 这些基本操作构成了双向链表的基本操作集合,使得我们可以对链表进行创建、读取、修改和删除等操作,是理解和实现链表数据结构的关键。双向链表相比于单链表的优点在于可以从两个方向遍历,方便在链表中间进行插入和删除操作,但同时需要更多的内存来存储额外的指针。在实际编程中,选择使用哪种链表取决于具体的应用场景和性能需求。
2011-12-28 上传
源码,经典。 CARD *myinsert(LCARD *head, LCARD *insert) { LCARD *temp = NULL; if (head==NULL)//链表为空 { head = insert; insert->next = insert; insert->prior = insert; } else//链表非空 { temp = head; if (head->cardnum>insert->cardnum)//插入到头前边,并且把自己当作头 { head->prior->next = insert; insert->prior = head->prior; insert->next = head; head->prior = insert; head = insert; } if (insert->cardnum0<50)//小于50正向插入 { while ((temp->cardnum<insert->cardnum)&&(temp->next!=head))//循环 { temp = temp->next; } if (temp->cardnum>insert->cardnum)//第一个条件终止的 { temp->prior->next = insert; insert->prior = temp->prior; insert->next = temp; temp->prior = insert; } else//第二个条件终止的 { head->prior->next = insert; insert->prior = head->prior; insert->next = head; head->prior = insert; } } else//大于50反向插入 { while ((temp->cardnum>insert->cardnum)&&(temp->prior!=head))//循环,第二个条件禁止跑飞 { temp = temp->prior; } if (temp->cardnum<insert->cardnum)//只有第一个条件可以终止的 { temp->next->prior = insert; insert->next = temp->next; insert->prior = temp; temp->next = insert; } } } //printf("%d\t%d\n", insert->id, insert->cardnum); return head; } void swap_id(SWID *sw) { LCARD *temp = sw->head; if (sw->head->cardnum==sw->swapcardnum) { printf("out person cardnum=%d\n", sw->head->id); sw->head->id = sw->inID; return ; } if ((sw->swapcardnum0)<50) { while ((temp->cardnum!=sw->swapcardnum)&&(temp->next!=sw->head)) { temp = temp->next; } if (temp->cardnum==sw->swapcardnum) { printf("out person cardnum=%d\n", sw->head->id); temp->id = sw->inID; } } else { while ((temp->cardnum!=sw->swapcardnum)&&(temp->prior!=sw->head)) { temp = temp->prior; } if (temp->cardnum==sw->swapcardnum) { printf("out person cardnum=%d\n", sw->head->id); temp->id = sw->inID; } } } LCARD *mydel(LCARD *head, LCARD *del) { LCARD *temp = NULL; if (head==NULL)//没有链表 { printf("there is no card\n"); } else//有链表 { if(head->next==head)//链表里就有一个节点并且为头结点 { if (head->cardnum==del->cardnum) { free(head); head = NULL; } else { printf("in mydel error\n"); } } else//链表里有超过一个的节点 { temp = head; if (del->cardnum0<50)//成立则正向删除 { while ((temp->cardnum!=del->cardnum)&&(temp->next!=head)) { temp = temp->next; } if (temp->cardnum==del->cardnum) { temp->prior->next = temp->next; temp->next->prior = temp->prior; free(temp); } } else//反向删除 { while ((temp->cardnum!=del->cardnum)&&(temp->prior!=head)) { temp = temp->prior; } if (temp->cardnum==del->cardnum) { temp->prior->next = temp->next; temp->next->prior = temp->prior; free(temp); } } } } return head; }