上篇双链表中提到了带头节点的双链表,众所周知头节点是在首元节点之前附设的一个节点,其指针域指向首元节点。头节点的数据域可以不存储任何信息,也可存储与数据元素类型相同的其他附加信息。那么一个双链表如果不带头结点只包含由数据域和指针域组成的若干个节点那会是什么情况呢?具体见下图:
因此不带头节点的双链表与带头结点的双链表相比提高了空间利用率。双链表中元素结点的遍历需要用到头指针。一个双链表可以没有头结点,但不能没有头指针。
以下就是不带头节点的双链表不同语言的代码实现:
C语言(DoubleLinkedListWithoutHeadNode):
#ifndef DOUBLELINKEDLISTWITHOUTHEADNODE_H_INCLUDED
#define DOUBLELINKEDLISTWITHOUTHEADNODE_H_INCLUDED
typedef int ElemType;
typedef struct Node
{
ElemType elem;
struct Node *prior;
struct Node *next;
}LNode,*LinkedList;
void InitList(LinkedList *L)
{
(*L)=NULL;
}
void DestroyList(LinkedList *L)
{
LNode *p=(*L);
while((*L)!=NULL)
{
p=(*L);
(*L)=p->next;
free(p);
p=NULL;
}
}
void ClearList(LinkedList *L)
{
LNode *p=(*L);
while((*L)!=NULL)
{
p=(*L);
(*L)=p->next;
free(p);
}
}
int ListEmpty(LinkedList *L)
{
if((*L)==NULL)
{
return 1;
}
else
{
return 0;
}
}
int ListLength(LinkedList *L)
{
LNode *p=(*L);
int i=0;
while(p!=NULL)
{
i++;
p=p->next;
}
return i;
}
ElemType GetElem(LinkedList *L,int index)
{
if(index<0||index>=ListLength(L))
{
return -1;
}
int i=0;
LNode *p=(*L);
while(i<index)
{
p=p->next;
i++;
}
return p->elem;
}
int LocateElem(LinkedList *L,ElemType elem)
{
LNode *p=(*L);
int i=0;
while(p!=NULL)
{
if(p->elem==elem)
{
return i;
}
i++;
p=p->next;
}
return -1;
}
ElemType PriorElem(LinkedList *L,ElemType elem)
{
LNode *p=(*L);
while(p!=NULL)
{
if(p->elem==elem)
{
if(p->prior==NULL)
{
break;
}
return p->prior->elem;
}
p=p->next;
}
return -1;
}
ElemType NextElem(LinkedList *L,ElemType elem)
{
LNode *p=(*L);
while(p!=NULL)
{
if(p->elem==elem)
{
if(p->next==NULL)
{
break;
}
return p->next->elem;
}
p=p->next;
}
return -1;
}
void addFirst(LinkedList *L,ElemType elem)
{
if((*L)==NULL)
{
(*L)=(LNode*)malloc(sizeof(LNode));
(*L)->elem=elem;
(*L)->next=NULL;
(*L)->prior=NULL;
}
else
{
LNode *s;
s=(LNode*)malloc(sizeof(LNode));
s->elem=elem;
s->next=(*L);
s->prior=NULL;
(*L)->prior=s;
(*L)=s;
}
}
void addAfter(LinkedList *L,ElemType elem)
{
if((*L)==NULL)
{
(*L)=(LNode*)malloc(sizeof(LNode));
(*L)->elem=elem;
(*L)->next=NULL;
(*L)->prior=NULL;
}
else
{
LNode *p=(*L),*s;
s=(LNode*)malloc(sizeof(LNode));
s->elem=elem;
while(p->next!=NULL)
{
p=p->next;
}
s->next=p->next;
p->next=s;
s->prior=p;
}
}
int ListInsert(LinkedList *L,int index,ElemType elem)
{
if(index<0||index>ListLength(L))
{
return -1;
}
else if(index==0)
{
addFirst(L,elem);
return 1;
}
else if(index==ListLength(L))
{
addAfter(L,elem);
return 1;
}
else
{
LNode *p=(*L),*s;
int i=1;
s=(LNode*)malloc(sizeof(LNode));
s->elem=elem;
while(i<index)
{
i++;
p=p->next;
}
s->next=p->next;
s->prior=p;
p->next=s;
s->next->prior=s;
}
}
int ListDelete(LinkedList *L,int index)
{
if(index<0||index>=ListLength(L))
{
return -1;
}
if(index==0)
{
if(ListLength(L)==1)
{
free((*L));
(*L)=NULL;
return 1;
}
LNode *del=(*L);
(*L)=del->next;
del->next=NULL;
del->elem=NULL;
free(del);
del=NULL;
(*L)->prior=NULL;
return 1;
}
int i=0;
LNode *p=(*L),*del;
while(i<index&&p->next!=NULL)
{
p=p->next;
i++;
}
del=p;
if(del->next!=NULL)
{
del->next->prior=del->prior;
del->prior->next=del->next;
free(del);
del=NULL;
return 1;
}
else
{
del->prior->next=NULL;
del->prior=NULL;
free(del);
del=NULL;
return 1;
}
}
void TraverseList(LinkedList *L)
{
LNode *p=(*L);
while(p!=NULL)
{
printf("%d\t",p->elem);
p=p->next;
}
printf("\n");
}
void TraverseListByReverseOrder(LinkedList *L)
{
if(ListEmpty(L))
{
printf("\n");
}
else
{
LNode *p=(*L);
while(p->next!=NULL)
{
p=p->next;
}
while(p!=NULL)
{
printf("%d\t",p->elem);
p=p->prior;
}
printf("\n");
}
}
#endif // DOUBLELINKEDLISTWITHOUTHEADNODE_H_INCLUDED
Java语言:
package DataStructure.LinearList;
public class LinkedList1 {
protected Object elem;
protected LinkedList1 next;
protected LinkedList1 prior;
public LinkedList1(Object elem)
{
this.elem=elem;
}
public LinkedList1(){}
}
package DataStructure.LinearList;
public class DoubleLinkedListWithoutHeadNode {
private LinkedList1 list;
public void InitList()
{
list=null;
}
public Boolean DestoryList()
{
LinkedList1 temp=list;
while (list!=null)
{
temp=list;
list=temp.next;
temp.elem=null;
temp.prior=null;
temp.next=null;
temp=null;
}
return true;
}
public Boolean ClearList()
{
LinkedList1 temp=list;
while (list!=null)
{
temp=list;
list=temp.next;
temp.elem=null;
temp.prior=null;
temp.next=null;
temp=null;
}
return true;
}
public Boolean ListEmpty()
{
if (list!=null)
{
return false;
}
else
{
return true;
}
}
public int ListLength()
{
LinkedList1 temp=list;
int i=0;
while (temp!=null)
{
i++;
temp=temp.next;
}
return i;
}
public Object GetElem(int index)
{
if(index<0||index>=this.ListLength())
{
return -1;
}
else {
LinkedList1 temp=list;
int i=0;
while (i<index)
{
i++;
temp=temp.next;
}
return temp.elem;
}
}
public int LocateElem(Object elem)
{
LinkedList1 temp=list;
for(int i=0;i<this.ListLength();i++)
{
if (temp.elem.equals(elem))
{
return i;
}
else
{
temp=temp.next;
}
}
return -1;
}
public Object PriorElem(Object elem)
{
int i=0;
LinkedList1 temp=list;
while (i<this.ListLength())
{
if (temp.elem.equals(elem))
{
try {
return temp.prior.elem;
}
catch (NullPointerException e)
{
return -1;
}
}
else
{
temp=temp.next;
}
i++;
}
return -1;
}
public Object NextElem(Object elem)
{
int i=0;
LinkedList1 temp=list;
while (i<this.ListLength()-1)
{
if (temp.elem.equals(elem))
{
return temp.next.elem;
}
else
{
temp=temp.next;
}
i++;
}
return -1;
}
public Boolean ListInsert(Object elem,int index)
{
if(index<0||index>this.ListLength())
{
return false;
}
else if(index==0)
{
this.addFirst(elem);
return true;
} else if (index==this.ListLength()) {
this.addAfter(elem);
return true;
}
else
{
LinkedList1 temp=list;
LinkedList1 node=new LinkedList1(elem);
int i=0;
while (i<index)
{
i++;
temp=temp.next;
}
node.next=temp.next;
node.next.prior=node;
node.prior=temp;
node.prior.next=node;
return true;
}
}
public void addFirst(Object elem)
{
if(list==null)
{
list=new LinkedList1(elem);
list.prior=null;
list.next=null;
}
else {
LinkedList1 node = new LinkedList1(elem);
node.next = list;
list.prior = node;
list = node;
}
}
public void addAfter(Object elem)
{
int i=0;
LinkedList1 temp=list;
if (this.ListLength()==0)
{
addFirst(elem);
}
else
{
while (i<this.ListLength()-1)
{
temp=temp.next;
i++;
}
LinkedList1 node=new LinkedList1(elem);
node.next=temp.next;
temp.next=node;
node.prior=temp;
}
}
public Boolean DeleteElem(int index)
{
if(index<0||index>this.ListLength()-1)
{
return false;
}
if(index==0)
{
if(this.ListLength()==1)
{
list.elem=null;
list.prior=null;
list.next=null;
list=null;
return true;
}
else
{
LinkedList1 del=list;
list=del.next;
del.elem=null;
del.prior=null;
del.next=null;
list.prior=null;
return true;
}
}
else
{
LinkedList1 temp=list;
for (int i = 0; i < index-1; i++) {
temp=temp.next;
}
LinkedList1 delete=temp.next;
if(delete.next!=null)
{
temp.next=delete.next;
delete.next.prior=temp;
delete.next=null;
delete.prior=null;
}
else
{
delete.prior.next=null;
delete.prior=null;
delete=null;
}
return true;
}
}
public void TraverseList()
{
LinkedList1 temp=list;
while(temp!=null)
{
System.out.print(temp.elem+"\t");
temp=temp.next;
}
System.out.println("");
}
public void TraverseListByReverseOrder()
{
int i=0;
LinkedList1 temp=list;
while (i<this.ListLength()-1)
{
temp=temp.next;
i++;
}
while (temp!=null)
{
System.out.print(temp.elem+"\t");
temp=temp.prior;
}
System.out.println("");
}
}