双向链表
在线性链式存储结构的结点中只有一个指示直接后继的指针域,由此,从某个结点出发只能顺指针往后寻查其他结点。若要寻查结点的直接前趋,则需从表头指针出发。换句话说,在单链表中,NextElem的执行时间是o(1),而PriorElem的执行时间为O(n)。为克服单链表这种单向性的缺点,可利用双向链表。
实现代码:
//双链循环线性表的表示与实现 #include <stdio.h> #include <stdlib.h> /****************************************************************************** /* 数据类型和常量定义 /******************************************************************************/ #define TURE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status; typedef int ElemType; /****************************************************************************** /* 数据结构声明 /******************************************************************************/ /* 线性表的双向链表存储结构 */ typedef struct DuLNode { ElemType data; struct DuLNode *prior; struct DuLNode *next; } DuLNode, *DuLinkList; //初始化双链循环线性表 Status InitList_DuL(DuLinkList &L) { L = (DuLinkList)malloc(sizeof(DuLNode)); L->next = L->prior = L; return OK; } //获取双链循环线性表中的元素 DuLNode * GetElemP_Dul(DuLinkList L, int i) { int j; struct DuLNode *p = L; if (i < 1) //非法i值 return NULL; if (p->next == L) //空双向循环链表 return L; p = L->next; j = 1; //初始化, p指向第一个结点, j为计数器 while(p != L && j < i) { //顺指针向后查找, 直到p指向第i个元素或p指向头结点 p = p->next; ++j; } return p; } //插入元素 Status ListInsert_DuL(DuLinkList &L, int i, ElemType e) { //在带头结点的双链循环线性表L中第i个位置之前插入元素e //i的合法值为1 <= i <= 表长 + 1 struct DuLNode *p = NULL; struct DuLNode *s = NULL; if (!(p = GetElemP_Dul(L, i))) return ERROR; if(!(s = (DuLinkList)malloc(sizeof(DuLNode)))) return ERROR; s->data = e; s->prior = p->prior; p->prior->next = s; s->next = p; p->prior = s; return OK; } //删除元素 Status ListDelete_DuL(DuLinkList &L, int i, ElemType &e) { //在带头结点的双链线性表L中, 删除第i个元素, 并由e返回其值 //i的合法值为1 <= i <= 表长 struct DuLNode *p = NULL; if (!(p = GetElemP_Dul(L, i)) || L == GetElemP_Dul(L, i)) return ERROR; e = p->data; p->prior->next = p->next; p->next->prior = p->prior; free(p); return OK; } //遍历线性表 Status ListTraverse_DuL(DuLinkList &L, Status (*Visit)(ElemType)) { printf("traverse list: "); struct DuLNode *p = L->next; //略过头结点 while (p != L) { Visit(p->data); p = p->next; } return OK; } //访问线性表中的元素 Status Visit(ElemType e) { printf("%d ", e); return OK; } //测试函数 void main() { DuLinkList L; ElemType e; InitList_DuL(L); //插入元素 if (OK == ListInsert_DuL(L, 0, 55)) printf("insert 55 succeed!\n"); if (OK == ListInsert_DuL(L, 1, 56)) printf("insert 56 succeed!\n"); ListTraverse_DuL(L, Visit); printf("\n"); if (OK == ListInsert_DuL(L, 2, 57)) printf("insert 57 succeed!\n"); if (OK == ListInsert_DuL(L, 1, 58)) printf("insert 58 succeed!\n"); ListTraverse_DuL(L, Visit); printf("\n"); //删除元素 if (OK == ListDelete_DuL(L, 1, e)) printf("the %dst elem deleted!\n", 1); if (OK == ListDelete_DuL(L, 3, e)) printf("the %drd elem deleted!\n", 3); if (OK == ListDelete_DuL(L, 4, e)) printf("the %dth elem deleted!\n", 4); else printf("delete the %dth elem failed!\n", 4); if (OK == ListDelete_DuL(L, 1, e)) printf("the %dst elem deleted!\n", 1); ListTraverse_DuL(L, Visit); printf("\n"); if (OK == ListDelete_DuL(L, 1, e)) printf("the %dst elem deleted!\n", 1); ListTraverse_DuL(L, Visit); printf("\n"); }