1.数据类型定义
在代码中为了清楚的表示一些错误和函数运行状态,我们预先定义一些变量来表示这些状态。在head.h头文件中有如下定义:
//定义数据结构中要用到的一些变量和类型
#ifndef HEAD_H
#define HEAD_H
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2 //分配内存出错
typedef int Status; //函数返回值类型
typedef int ElemType; //用户定义的数据类型
#endif
2.双链表数据结构实现
typedef struct LNode{
ElemType data;
struct LNode *pre;
struct LNode *next;
}LNode,*Link;
typedef struct DLink{
Link head;
Link tail;
int len;
}DLink,*DLinkList;
3.双链表代码实现
DLinkList.h文件如下:
#ifndef DLINKLIST_H
#define DLINKLIST_H
#include "head.h"
typedef struct LNode{
ElemType data;
struct LNode *pre;
struct LNode *next;
}LNode,*Link;
typedef struct DLink{
Link head;
Link tail;
int len;
}DLink,*DLinkList;
Status MakeNode(Link &p,ElemType e){
p=(Link)malloc(sizeof(LNode));
if(!p) return OVERFLOW;
p->data=e;
return OK;
}
Status FreeNode(Link &p){
free(p);
p=NULL;
return OK;
}
Status InitList(DLinkList &L){
Link head=(Link)malloc(sizeof(LNode));
if(!head) return OVERFLOW;
Link tail=(Link)malloc(sizeof(LNode));
if(!tail) return OVERFLOW;
head->data=-99999;
tail->data=9999;
head->next=tail;
tail->next=head;
head->pre=tail;
tail->pre=head;
L=(DLinkList)malloc(sizeof(DLink));
if(!L) return OVERFLOW;
L->head=head;
L->tail=tail;
L->len=0;
return OK;
}
Link getPreLink(DLinkList L,int i){
Link p=L->head;
for (int n=1;n<i;n++)
{
p=p->next;
}
return p;
}
Link getNextLink(DLinkList L,int i){
Link p=L->head;
for (int n=0;n<i;n++)
{
p=p->next;
}
return p;
}
Status DListInsert(DLinkList &L,int i,ElemType e){
if(i<1 ||i>L->len+1) return ERROR;
Link p=getPreLink(L,i);
Link n=getNextLink(L,i);
Link link;
MakeNode(link,e);
p->next=link;
link->next=n;
n->pre=link;
link->pre=p;
L->len++;
return OK;
}
Status DLinkDelete(DLinkList &L,int i,ElemType &e){
if(i<1 ||i>L->len) return ERROR;
Link p=getPreLink(L,i);
Link n=getNextLink(L,i+1);
Link link=p->next;
p->next=link->next;
n->pre=link->pre;
e=link->data;
FreeNode(link);
link=NULL;
return OK;
}
Status printDLinkHead(DLinkList L){
Link Ln=L->head->next;
printf("head->");
while(Ln!=L->tail){
printf("%d->",Ln->data);
Ln=Ln->next;
}
printf("tail");
return true;
}
Status printDLinkTail(DLinkList L){
Link Ln=L->tail->pre;
printf("tail->");
while(Ln!=L->head){
printf("%d->",Ln->data);
Ln=Ln->pre;
}
printf("head");
return true;
}
#endif
4.双链表测试
#include "DLinkList.h"
void main(){
DLinkList L;
InitList(L);
for(int i=1;i<10;i++)
DListInsert(L,i,i);
printf("\n从头遍历:");
printDLinkHead(L);
printf("\n从尾遍历:");
printDLinkTail(L);
DListInsert(L,5,55);
printf("\n第5位置插入55后从头遍历:");
printDLinkHead(L);
printf("\n第5位置插入55后从尾遍历:");
printDLinkTail(L);
ElemType e;
DLinkDelete(L,6,e);
printf("\n删除第6位置后从头遍历:");
printDLinkHead(L);
printf("\n删除第6位置后从尾遍历:");
printDLinkTail(L);
}
5.测试结果
从头遍历:head->1->2->3->4->5->6->7->8->9->tail
从尾遍历:tail->9->8->7->6->5->4->3->2->1->head
第5位置插入55后从头遍历:head->1->2->3->4->55->5->6->7->8->9->tail
第5位置插入55后从尾遍历:tail->9->8->7->6->5->55->4->3->2->1->head
删除第6位置后从头遍历:head->1->2->3->4->55->6->7->8->9->tail
删除第6位置后从尾遍历:tail->9->8->7->6->55->4->3->2->1->head