1.代码
#include <stdio.h>
#include <malloc.h>
/**
* Double linked list of the integers.The key is char.
*/
typedef struct DoubleLinkedNode{
char data;
struct DoubleLinkedNode *previous;
struct DoubleLinkedNode *next;
}DLNode ,* DLNodePtr;
/**
* Initialize the list with a header.
* @return The pointer to the header.
*/
DLNodePtr initLinkList(){
DLNodePtr tempHeader = (DLNodePtr)malloc(sizeof(struct DoubleLinkedNode));
tempHeader->data='\0';
tempHeader->previous=NULL;
tempHeader->next=NULL;
return tempHeader;
}//of initLinkList
/**
* Print the list.
* @param paraHeader The header of the list.
*/
void printList(DLNodePtr paraHeader){
DLNodePtr p=paraHeader->next;
while (p != NULL){
printf("%c",p->data);
p = p->next;
}//of while
printf("\r\n");
}//of printList
/**
* Insert an element to the given position.
* @param paraHeader The header of the list.
* @param paraChar The given char.
* @param paraPosition The given position.
*/
void insertElement(DLNodePtr paraHeader ,char paraChar,int paraPosition){
DLNodePtr p,q,r;
//step 1.Search to the position.
p = paraHeader;
int i;
for( i=0;i<paraPosition;i++){
p = p->next;
if(p==NULL){
printf("The position %d is beyond the scope of the list.",paraPosition);
return;
}//of if
}//of for i
//step2.Construct a new node
q=(DLNodePtr)malloc(sizeof(struct DoubleLinkedNode));
q->data =paraChar;
//step3 Now link
r=p->next;
q->next=p->next;
q->previous=p;
p->next=q;
if(r!=NULL) {
r->previous=q;
}//of if
}//of insertElement
/**
* Delete an element from the list.
* @param paraHeader The header of the list.
* @param paraChar The given char.
*/
void deleteElement(DLNodePtr paraHeader ,char paraChar){
DLNodePtr p,q,r;
p=paraHeader;
//step 1.locate。
while((p->next!=NULL)&&(p->next->data!=paraChar)){
p=p->next;
}//of while
//step2.Error check
if(p->next==NULL){
printf("The char %c does not exist.\r\n",paraChar) ;
return;
}//of if
//step3.Change links
q=p->next;
r=q->next;
p->next=r;
if(r!=NULL){
r->previous =p;
}//of if
//step4 free the space.
free(q) ;
}//of deleteElemnet
/**
* Unit test
*/
void insertDeleteTest() {
//step1 initialize an empty list
DLNodePtr tempList =initLinkList() ;
printList(tempList);
//step2.Add some characters.
insertElement(tempList,'H',0);
insertElement(tempList,'e',1);
insertElement(tempList,'l',2);
insertElement(tempList,'l',3);
insertElement(tempList,'o',4);
insertElement(tempList,'!',5);
printList(tempList);
//step3 delete some characters (the first occurrence)
deleteElement(tempList,'e');
deleteElement(tempList,'a');
deleteElement(tempList,'o');
printList(tempList);
//step4.inser to a given position.
insertElement(tempList,'o',1);
printList(tempList);
}//of appendinsertDeleteTest
/**
* Adderss test:beyond the book.
*/
void basicAddressTest() {
DLNode tempNode1 ,tempNode2 ;
tempNode1.data =4;
tempNode1.next =NULL;
tempNode2.data =6;
tempNode2.next =NULL;
printf("The first node:%d, %d,%d\r\n ",&tempNode1,&tempNode1.data,&tempNode1.next);
printf("The second node:%d,%d,%d\r\n",&tempNode2,&tempNode2.data,&tempNode2.next);
tempNode1.next=&tempNode2;
}//of basicAddressTest
/**
* The entrance
*/
void main(){
insertDeleteTest();
basicAddressTest();
}//of main
2运行结果
3.小结
一、定义与特点
双向链表是在单链表的基础上,为每个节点增加了一个指向其直接前驱的指针域,从而形成了两个方向不同的链。这种结构使得双向链表中的每个节点都包含三个部分:前一个节点的指针(previous)、当前节点保存的元素(data)以及后一个节点的指针(next)。在双向链表的第一个节点,其prev指针为NULL;而在最后一个节点,其next指针为NULL。
二、优点与缺点
优点:双向性,可以方便地找到当前节点的前驱和后继,从而实现了双向遍历。这使得双向链表在需要双向查找节点值的情况下具有显著优势。
缺点:双向链表在增加和删除节点时相对复杂,因为需要处理两个方向的指针,相较于单向链表会多分配一个指针存储空间。
三、常见操作
双向链表支持多种常见操作,如向列表尾部添加新项(append)、向链表的特定位置插入新项(insert)、获取对应位置的元素(get)、返回元素在列表中的索引(indexOf)、删除某位置的元素(delete)。