1、节点定义
- typedef struct DListElement_
- {
- void * data;
- struct DListElement_ *prev;
- struct DListElement_ *next;
- }DListElement;
2、链表定义
- typedef struct DList_
- {
- int size;
- DListElement *head;
- DListElement *tail;
- }Dlist;
3、从某个节点的头部插入
int dlist_ins_prev(Dlist *list, DListElement *element, const void *data)
{
DListElement *new_element;
if (element == NULL && list->size != 0)//给定的节点无效
return -1;
if ((new_element = (DListElement *)malloc(sizeof(DListElement))) == NULL)
return -1;
new_element->data = (void *)data;
if (list->size == 0)//插入的为头节点
{
list->head = new_element;
list->tail = new_element;
new_element->prev = NULL;
new_element->next = NULL;
}
else//剩下的情况插入操作都是一样的
{
element->prev->next = new_element;
new_element->prev = element->prev;
element->prev = new_element;
new_element->next = element;
}
list->size++;
return;
}
4、从某个节点的尾部插入
int dlist_ins_next(Dlist *list, DListElement *element, const void *data)
{
DListElement *new_element;
if (element == NULL && list->size != 0)
return -1;
if ((new_element = (DListElement *)malloc(sizeof(DListElement))) == NULL)
return -1;
new_element->data = (void *)data;
if (list->size == 0)//插入的为头节点
{
list->head = new_element;
list->tail = new_element;
new_element->prev = NULL;
new_element->next = NULL;
}
else
{
if (element->next == NULL)//插入的为尾节点
{
new_element->next = NULL;
list->tail = new_element;
}
else
{
new_element->next = element->next;
element->next->prev = new_element;
}
element->next = new_element;
new_element->prev = element;
}
list->size++;
return;
}
5、删除节点
int dlist_rm_node(Dlist *list, DListElement *element, void **data)
{
if (element == NULL || list->size == 0)
return -1;
//这里有一个关于二重指针作为传出参数的操作,主要原因是,因为我们需要传出的是一个一重指针的值,所以需要传入他的地址,即二重指针来获取。如果传入一重指针,则最后的结果和两个变量的问题一样。
*data = element->data;//获取节点的数据
if (element->prev == NULL)//删除头部节点
{
list->head = element->next;
list->head->prev = NULL;
}
if (element->next == NULL)//删除尾部节点
{
list->tail = element->prev;
list->tail->next = NULL;
}
else//删除中间节点
{
element->prev = element->next;
element->next->prev = element->prev;
}
if (element != NULL)
{
free(element);
}
list->size--;
return;
}
6、链表的遍历
//遍历整个链表
int dlist_ergodic(Dlist *list)
{
DListElement *p;
p = list->head;
while (p->next != NULL)
{
printf("%d-", (int)(p->data));
p = p->next;
}
printf("%d-", (int)(p->data));
printf("\n链表的长度为%d.\n", list->size);
return;
}
首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下:
- #ifndef DList_H
- #define DList_H
- typedef int Item;
- typedef struct Node * PNode;
- typedef PNode Position;
- /*定义节点类型*/
- typedef struct Node
- {
- Item data; /*数据域*/
- PNode previous; /*指向前驱*/
- PNode next; /*指向后继*/
- }Node;
- /*定义链表类型*/
- typedef struct
- {
- PNode head; /*指向头节点*/
- PNode tail; /*指向尾节点*/
- int size;
- }DList;
- /*分配值为i的节点,并返回节点地址*/
- Position MakeNode(Item i);
- /*释放p所指的节点*/
- void FreeNode(PNode p);
- /*构造一个空的双向链表*/
- DList* InitList();
- /*摧毁一个双向链表*/
- void DestroyList(DList *plist);
- /*将一个链表置为空表,释放原链表节点空间*/
- void ClearList(DList *plist);
- /*返回头节点地址*/
- Position GetHead(DList *plist);
- /*返回尾节点地址*/
- Position GetTail(DList *plist);
- /*返回链表大小*/
- int GetSize(DList *plist);
- /*返回p的直接后继位置*/
- Position GetNext(Position p);
- /*返回p的直接前驱位置*/
- Position GetPrevious(Position p);
- /*将pnode所指节点插入第一个节点之前*/
- PNode InsFirst(DList *plist,PNode pnode);
- /*将链表第一个节点删除并返回其地址*/
- PNode DelFirst(DList *plist);
- /*获得节点的数据项*/
- Item GetItem(Position p);
- /*设置节点的数据项*/
- void SetItem(Position p,Item i);
- /*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/
- PNode Remove(DList *plist);
- /*在链表中p位置之前插入新节点S*/
- PNode InsBefore(DList *plist,Position p,PNode s);
- /*在链表中p位置之后插入新节点s*/
- PNode InsAfter(DList *plist,Position p,PNode s);
- /*返回在链表中第i个节点的位置*/
- PNode LocatePos(DList *plist,int i);
- /*依次对链表中每个元素调用函数visit()*/
- void ListTraverse(DList *plist,void (*visit)());
- #endif
接下来逐个实现其功能,DList.c内容如下:
- #include"DList.h"
- #include<malloc.h>
- #include<stdlib.h>
- /*分配值为i的节点,并返回节点地址*/
- Position MakeNode(Item i)
- {
- PNode p = NULL;
- p = (PNode)malloc(sizeof(Node));
- if(p!=NULL)
- {
- p->data = i;
- p->previous = NULL;
- p->next = NULL;
- }
- return p;
- }
- /*释放p所指的节点*/
- void FreeNode(PNode p)
- {
- free(p);
- }
- /*构造一个空的双向链表*/
- DList * InitList()
- {
- DList *plist = (DList *)malloc(sizeof(DList));
- PNode head = MakeNode(0);
- if(plist!=NULL)
- {
- if(head!=NULL)
- {
- plist->head = head;
- plist->tail = head;
- plist->size = 0;
- }
- else
- return NULL;
- }
- return plist;
- }
- /*摧毁一个双向链表*/
- void DestroyList(DList *plist)
- {
- ClearList(plist);
- free(GetHead(plist));
- free(plist);
- }
- /*判断链表是否为空表*/
- int IsEmpty(DList *plist)
- {
- if(GetSize(plist)==0&&GetTail(plist)==GetHead(plist))
- return 1;
- else
- return 0;
- }
- /*将一个链表置为空表,释放原链表节点空间*/
- void ClearList(DList *plist)
- {
- PNode temp,p;
- p = GetTail(plist);
- while(!IsEmpty(plist))
- {
- temp = GetPrevious(p);
- FreeNode(p);
- p = temp;
- plist->tail = temp;
- plist->size--;
- }
- }
- /*返回头节点地址*/
- Position GetHead(DList *plist)
- {
- return plist->head;
- }
- /*返回尾节点地址*/
- Position GetTail(DList *plist)
- {
- return plist->tail;
- }
- /*返回链表大小*/
- int GetSize(DList *plist)
- {
- return plist->size;
- }
- /*返回p的直接后继位置*/
- Position GetNext(Position p)
- {
- return p->next;
- }
- /*返回p的直接前驱位置*/
- Position GetPrevious(Position p)
- {
- return p->previous;
- }
- /*将pnode所指节点插入第一个节点之前*/
- PNode InsFirst(DList *plist,PNode pnode)
- {
- Position head = GetHead(plist);
- if(IsEmpty(plist))
- plist->tail = pnode;
- plist->size++;
- pnode->next = head->next;
- pnode->previous = head;
- if(head->next!=NULL)
- head->next->previous = pnode;
- head->next = pnode;
- return pnode;
- }
- /*将链表第一个节点删除,返回该节点的地址*/
- PNode DelFirst(DList *plist)
- {
- Position head = GetHead(plist);
- Position p=head->next;
- if(p!=NULL)
- {
- if(p==GetTail(plist))
- plist->tail = p->previous;
- head->next = p->next;
- head->next->previous = head;
- plist->size--;
- }
- return p;
- }
- /*获得节点的数据项*/
- Item GetItem(Position p)
- {
- return p->data;
- }
- /*设置节点的数据项*/
- void SetItem(Position p,Item i)
- {
- p->data = i;
- }
- /*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/
- PNode Remove(DList *plist)
- {
- Position p=NULL;
- if(IsEmpty(plist))
- return NULL;
- else
- {
- p = GetTail(plist);
- p->previous->next = p->next;
- plist->tail = p->previous;
- plist->size--;
- return p;
- }
- }
- /*在链表中p位置之前插入新节点s*/
- PNode InsBefore(DList *plist,Position p,PNode s)
- {
- s->previous = p->previous;
- s->next = p;
- p->previous->next = s;
- p->previous = s;
- plist->size++;
- return s;
- }
- /*在链表中p位置之后插入新节点s*/
- PNode InsAfter(DList *plist,Position p,PNode s)
- {
- s->next = p->next;
- s->previous = p;
- if(p->next != NULL)
- p->next->previous = s;
- p->next = s;
- if(p = GetTail(plist))
- plist->tail = s;
- plist->size++;
- return s;
- }
- /*返回在链表中第i个节点的位置*/
- PNode LocatePos(DList *plist,int i)
- {
- int cnt = 0;
- Position p = GetHead(plist);
- if(i>GetSize(plist)||i<1)
- return NULL;
- while(++cnt<=i)
- {
- p=p->next;
- }
- return p;
- }
- /*依次对链表中每个元素调用函数visit()*/
- void ListTraverse(DList *plist,void (*visit)())
- {
- Position p = GetHead(plist);
- if(IsEmpty(plist))
- exit(0);
- else
- {
- while(p->next!=NULL)
- {
- p = p->next;
- visit(p->data);
- }
- }
- }
接下来进行测试,Test.h内容如下:
- #include"DList.h"
- #include<stdio.h>
- void print(Item i)
- {
- printf("数据项为%d \n",i);
- }
- main()
- {
- DList *plist = NULL;
- PNode p = NULL;
- plist = InitList();
- p = InsFirst(plist,MakeNode(1));
- InsBefore(plist,p,MakeNode(2));
- InsAfter(plist,p,MakeNode(3));
- printf("p前驱位置的值为%d\n",GetItem(GetPrevious(p)));
- printf("p位置的值为%d\n",GetItem(p));
- printf("p后继位置的值为%d\n",GetItem(GetNext(p)));
- printf("遍历输出各节点数据项:\n");
- ListTraverse(plist,print);
- printf("除了头节点该链表共有%d个节点\n",GetSize(plist));
- FreeNode(DelFirst(plist));
- printf("删除第一个节点后重新遍历输出为:\n");
- ListTraverse(plist,print);
- printf("除了头节点该链表共有%d个节点\n",GetSize(plist));
- DestroyList(plist);
- printf("链表已被销毁\n");
- }