一.带头,双向
1.带头可能对初学者来说是一种优势,因为有了头(哨兵位),不需要运用二级指针,因为第一的位置已经确定,(二级指针用在不带头的修改头的值), 相对来说可能更加好理解,但是带头,这个头哨兵位存储的数据却没有很大的意义,实践意义并不大.
2.双向的链表,有一个好处,解决了单链表不能够找到前一个的问题,链表之间形成了循环,数据的修改更加便捷,当然相对而言也是更加复杂的.
二.带头双向链表的实现
头文件
#pragma once #include<stdio.h> #include<stdlib.h> // 带头+双向+循环链表增删查改实现 typedef int LTDataType; typedef struct ListNode { LTDataType data; struct ListNode* next; struct ListNode* prev; }ListNode; // 创建返回链表的头结点. ListNode* ListInitate(); // 双向链表销毁 void ListDestory(ListNode* pHead); // 双向链表打印 void ListPrint(ListNode* pHead); // 双向链表尾插 void ListPushBack(ListNode* pHead, LTDataType x); // 双向链表尾删 void ListPopBack(ListNode* pHead); // 双向链表头插 void ListPushFront(ListNode* pHead, LTDataType x); // 双向链表头删 void ListPopFront(ListNode* pHead); // 双向链表查找 ListNode* ListFind(ListNode* pHead, LTDataType x); // 双向链表在pos的前面进行插入 void ListInsert(ListNode* pos, LTDataType x); // 双向链表删除pos位置的节点 void ListErase(ListNode* pos);
主体部分的实现(realize.c)
#include"twohead.h" //创建一个节点 ListNode* CreateNode(LTDataType x) { ListNode* newnode = (ListNode*)malloc(sizeof(ListNode)); if (newnode == NULL) { printf("malloc failed"); exit(-1); } newnode->data = x; newnode->next = NULL; newnode->prev = NULL; return newnode; } //链表的初始化 ListNode* ListInitate() { ListNode* phead = CreateNode(-1); phead->next = phead; phead->prev = phead; return phead; } //链表的打印 void ListPrint(ListNode* pHead) { if (pHead == NULL) return; printf("哨兵位<=>"); ListNode* cur = pHead->next; while (cur != pHead) { printf("%d<=>", cur->data); cur = cur->next; } } //链表的销毁 void ListDestory(ListNode* pHead) { free(pHead); pHead = NULL; } //链表的头插 void ListPushFront(ListNode* pHead, LTDataType x) { if (pHead == NULL) return; ListNode* cur = CreateNode(x); cur->next = pHead->next; pHead->next = cur; cur->prev = cur->next->prev; cur->next->prev = cur; } //链表的头删 void ListPopFront(ListNode* pHead) { if (pHead == NULL) return; if (pHead->next == pHead) return; pHead->next = pHead->next->next; pHead->next->prev->prev = pHead; } //链表的尾插 void ListPushBack(ListNode* pHead, LTDataType x) { if (pHead == NULL) return; ListNode* cur = CreateNode(x); pHead->prev->next = cur; cur->prev = pHead->prev; cur->next = pHead; pHead->prev = cur; } //链表的尾删 void ListPopBack(ListNode* pHead) { if (pHead == NULL) return; if (pHead->next == pHead) return; pHead->prev->prev->next = pHead; pHead->prev = pHead->prev->prev; } //链表的查找 ListNode* ListFind(ListNode* pHead, LTDataType x) { if (pHead == NULL) return NULL; if (pHead->next == pHead) return NULL; ListNode* cur = pHead->next; while (cur!=pHead) { if (cur->data == x) return cur; cur = cur->next; } return NULL; } //链表pos位置之前的插入 void ListInsert(ListNode* pos, LTDataType x) { if (pos == NULL) return; ListNode* cur = CreateNode(x); pos->prev->next = cur; cur->next = pos; cur->prev = pos->prev->next; pos->prev = cur; } //链表pos位置的删除 void ListErase(ListNode* pos) { if (pos == NULL) return; pos->prev->next = pos->next; pos->next->prev = pos->prev; }
测试样例的是实现
#include"twohead.h" void test1() { ListNode* head = ListInitate(); ListPushFront(head, 1); ListPushFront(head, 2); ListPushFront(head, 3); ListPushFront(head, 4); ListPushFront(head, 5); ListPushFront(head, 6); ListPrint(head); ListDestory(head); } void test2() { ListNode* head = ListInitate(); ListPushFront(head, 1); ListPushFront(head, 2); ListPushFront(head, 3); ListPushFront(head, 4); ListPushFront(head, 5); ListPushFront(head, 6); ListPopFront(head); ListPopFront(head); ListPopFront(head); ListPopFront(head); ListPopFront(head); ListPopFront(head); ListPopFront(head); ListPopFront(head); ListPopFront(head); ListPopFront(head); ListPrint(head); ListDestory(head); } void test3() { ListNode* head = ListInitate(); ListPushBack(head, 1); ListPushBack(head, 2); ListPushBack(head, 3); ListPushBack(head, 4); ListPushBack(head, 5); ListPushBack(head, 6); ListPrint(head); ListDestory(head); } void test4() { ListNode* head = ListInitate(); ListPushBack(head, 1); ListPushBack(head, 2); ListPushBack(head, 3); ListPushBack(head, 4); ListPushBack(head, 5); ListPushBack(head, 6); ListPopBack(head); ListPopBack(head); ListPopBack(head); ListPopBack(head); ListPrint(head); ListDestory(head); } void test5() { ListNode* head = ListInitate(); ListPushBack(head, 1); ListPushBack(head, 2); ListPushBack(head, 3); ListPushBack(head, 4); ListPushBack(head, 5); ListPushBack(head, 6); ListPrint(head); printf("\n"); ListNode*cur= ListFind(head, 102); printf("%p", cur); ListDestory(head); } void test6() { ListNode* head = ListInitate(); ListPushBack(head, 1); ListPushBack(head, 2); ListPushBack(head, 3); ListPushBack(head, 4); ListPushBack(head, 5); ListPushBack(head, 6); ListPrint(head); printf("\n"); ListNode* cur = ListFind(head, 4); ListInsert(cur, 100); ListPrint(head); ListDestory(head); } void test7() { ListNode* head = ListInitate(); ListPushBack(head, 1); ListPushBack(head, 2); ListPushBack(head, 3); ListPushBack(head, 4); ListPushBack(head, 5); ListPushBack(head, 6); ListPrint(head); printf("\n"); ListNode* cur = ListFind(head, 4); ListErase(cur); ListPrint(head); ListDestory(head); } int main() { //test1(); //test2(); //test3(); //test4(); //test5(); //test6(); //test7(); return 0; }