数据结构----双向不循环链表
以下内容只是学习记录:
一、背景
之前讨论的链式存储结构的节点中只有一个指示直接后继的指针域,因此,从某个节点出发只能顺时针往后查找其他节点。若要查询节点的直接前驱,则需要从表头触发,若是单循环则需要查找一个周期,换句话说,在单链表中,NextElem的执行时间为O(1),而PriorElem的执行时间为O(n)。为克服这个缺点,可以使用双向链表。
二、定义
顾名思义,在双向链表的节点中有两个指针域,一个指向直接后继,一个指向直接前驱,结构体定义如下:
#define ElemType int typedef struct Node { ElemType data; struct Node *prior;//指向前驱的指针 struct Node *next;//指向后继的指针 }Node, *PNode;
typedef struct List { PNode first;//头节点 PNode last;//尾节点 int size;//链表数据长度 }List;
三、代码实现
1、链表初始化
void InitDList(List *list)
{
Node *s = (Node *)malloc(sizeof(Node));
assert(s!=NULL);
list->first = list->last = s;
list->last->next = NULL;
list->first->prior = NULL;
/*list->last->prior = NULL;
list->first->next = NULL;*/ //这两行多余 因为first和last指向同一个地址
list->size = 0;
}
2、链表测试函数编写
#include "DList.h" void main() { List mylist; InitDList(&mylist); ElemType Item; Node *p = NULL; int select = 1; while (select) { printf("***************************************************\n"); printf("* [1] push_back [2] push_front *\n"); printf("* [3] show_list [4] pop_back *\n"); printf("* [5] pop_front [6] insert_val *\n"); printf("* [7] find [8] length *\n"); printf("* [9] delete_val [10] sort *\n"); printf("* [11] reverse [12] clear *\n"); printf("* [13] destroy [0] quit_system *\n"); printf("***************************************************\n"); printf("请选择:>"); scanf("%d", &select); if (select == 0) break; switch (select) { case 1: printf("请输入要插入的数据(-1结束):"); while (scanf("%d", &Item), Item != -1) { push_back(&mylist, Item); } break; case 2: printf("请输入要插入的数据(-1结束):"); while (scanf("%d", &Item), Item != -1) { //push_front(&mylist, Item); } break; case 3: show_list(&mylist); break; case 4: pop_back(&mylist); break; case 5: pop_front(&mylist); break; case 6: printf("请输入要插入的数据:"); scanf("%d", &Item); insert_val(&mylist, Item); break; case 7: printf("请输入要查找的数据:"); scanf("%d", &Item); p = find(&mylist, Item); if (p == NULL) { printf("要查找的数据在链表中不存在\n"); } else { printf("要查找的数据为:%d", p->data); } break; case 8: printf("链表的长度为:%d\n", length(&mylist)); break; case 9: printf("请输入要删除的值:"); scanf("%d", &Item); delete_val(&mylist, Item); break; case 10: sort(&mylist); break; case 11: reverse(&mylist); break; case 12: clear(&mylist); break; case 13: destroy(&mylist); break; case 14: break; default: printf("输入的命令错误,请重新输入.\n"); break; } } //destroy(&mylist); }
3、链表功能函数编写
#include "DList.h" void InitDList(List *list) { Node *s = (Node *)malloc(sizeof(Node)); assert(s!=NULL); list->first = list->last = s; list->last->next = NULL; list->first->prior = NULL; /*list->last->prior = NULL; list->first->next = NULL;*/ //这两行多余 因为first和last指向同一个地址 list->size = 0; } Node* _buynode(ElemType x) { Node *s = (Node *)malloc(sizeof(Node)); assert(s!=NULL); s->data = x; s->next = NULL; s->prior = NULL; return s; } void push_back(List *list, ElemType x) { Node *s = _buynode(x); s->prior = list->last; list->last->next = s; list->last = s; list->size++; } void push_front(List *list, ElemType x) { Node *s = _buynode(x); if (list->first == list->last) { s->prior = list->first; list->first->next = s; list->last = s; } else { s->next = list->first->next; s->next->prior = s; s->prior = list->first; list->first->next = s; } list->size++; } void show_list(List *list) { Node *p = list->first->next; while (p != NULL) { printf("%d->",p->data); p = p->next; } printf("Null."); } void pop_back(List *list) { if (list->size == 0) return; Node *p = list->last; p->prior->next = NULL; list->last = p->prior; free(p); p = NULL; list->size--; } void pop_front(List *list) { if (list->size == 0) return; Node *p = list->first->next; if (p == list->last) { list->last = list->first; list->first->next = NULL; free(p); p = NULL; } else { list->first->next = p->next; p->next->prior = list->first; free(p); p = NULL; } list->size--; } void insert_val(List *list, ElemType x)//前提是数据有序 { Node *p = list->first; while (p->next != NULL && p->next->data <= x) { p = p->next; } if (p->next == NULL) { push_back(list, x); } else { Node *q = _buynode(x); q->next = p->next; p->next->prior = q; q->prior = p; p->next = q; list->size++; } } Node *find(List *list, ElemType key) { Node *p = list->first; while (p->next != NULL && p->next->data != key) p = p->next; return p->next; } int length(List *list) { return list->size; } void delete_val(List *list, ElemType key) { if (list->size == 0) return; Node *p = find(list, key); if (p == NULL) { printf("要删除的值不存在。\n"); return; } if (p == list->last) { list->last = p->prior; list->last->next = NULL; free(p); p = NULL; } else { p->prior->next = p->next; p->next->prior = p->prior; free(p); p = NULL; } list->size--; } void sort(List *list) { if (list->size == 0 || list->size == 1) return; Node *s = list->first->next; Node *q = s->next; list->last = s; list->last->next = NULL; while (q != NULL) { s = q; q = q->next; Node *p = list->first; while (p->next != NULL && p->next->data <= s->data) p = p->next; if (p->next == NULL) { s->prior = list->last; s->next = NULL; list->last->next = s; list->last = s; list->size++; } else { s->next = p->next; s->next->prior = s; s->prior = p; p->next = s; list->size++; } } } void reverse(List *list) { if (list->size == 0 || list->size == 1) return; Node *s = list->first->next; Node *q = s->next; list->last = s; list->last->next = NULL; while (q != NULL) { s = q; q = q->next; s->next = list->first->next; list->first->next->prior = s; s->prior = list->first; list->first->next = s; } } void clear(List *list) { if (list->size == 0) return; Node *p = list->first->next; while (p != NULL) { if (p == list->last) { list->last = list->first; list->last->next = NULL; } else { p->next->prior = list->first; list->first->next = p->next; } free(p); p =list->first->next; } list->size = 0; } void destroy(List *list) { clear(list); free(list->first); list->first = list->last = NULL; }