(1)双向链表的定义
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
指针域:用于指向当前节点的直接前驱节点;
数据域:用于存储数据元素。
指针域:用于指向当前节点的直接后继节点;
(2).双向链表的建立
同单链表相比,双链表仅是各节点多了一个用于指向直接前驱的指针域。因此,我们可以在单链表的基础轻松实现对双链表的创建。
需要注意的是,与单链表不同,双链表创建过程中,每创建一个新节点,都要与其前驱节点建立两次联系,分别是:
将新节点的 prior 指针指向直接前驱节点;
将直接前驱节点的 next 指针指向新节点;
1.链表的建立
typedef struct DoubleLinkedNode{
char data;
struct DoubleLinkedNode *previous;
struct DoubleLinkedNode *next;
} DLNode, *DLNodePtr;
//创建链表每个节点包含两个指针域和一个数据域
这一步只是在单链表的基础上加了一个新的指针域
2.链表初始化
DLNodePtr initLinkList(){
DLNodePtr tempHeader = (DLNodePtr)malloc(sizeof(struct DoubleLinkedNode));
tempHeader->data = '\0';
tempHeader->previous = NULL;
tempHeader->next = NULL;
return tempHeader;
}//链表初始化,创建头节点
这一步与单链表的初始化相同
上文是链表的建立过程,下文则是基本函数的接口定义
3.链表的插入
(1).尾插法:
void appendElement(NodePtr paraHeader,char paraChar)
{
NodePtr p,q;
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
q->next = NULL;
p = paraHeader;
while(p->next!=NULL)
{
p = p->next;
}
p->next = q;
}//以上为单链表中的尾插基本操作
void appendElement(NodePtr paraHeader,char paraChar)
{
NodePtr p,q;
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
q->next = NULL;
p = paraHeader;
while(p->next!=NULL)
{
p = p->next;
}
p->next = q;
q->pervious = p;
}//两者操作区别不大只不过是将新加节点中的其中一个指针域的指向前一个节点
(2).头插法
void appendElement(NodePtr paraHeader,char paraChar)
{
NodePtr p,q;
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
q->next = NULL;
for(int i = 0; i < n; i++){
p = (NodePtr)malloc(sizeof(LNode));
p->data = Lnode[i];
p->next = q->next; //将节点p插在开始节点之前,头节点之后
q->next = p;
}
}//原单链表C语言代码
void appendElement(NodePtr paraHeader,char paraChar)
{
NodePtr p,q,r;
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
q->next = NULL;
q->previous = NULL;
p = temheader->next;
r = p;
temheader->next = q;
q->pervious = temheader;
p->pervious = q;
q->next = p;
}//双向链表头插法代码代码
(3).指定节点插入
void insertElement(NodePtr paraHeader,char paraChar,int paraPosition)
{
NodePtr p,q;
p = paraHeader;
for(int i = 0;i < paraPosition;i++)
{
p = p->next;
if(p==NULL)
{
printf("这个位置 %d 超出了节点的个数无法插入.",paraPosition);
return;
}
}
q=(NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
printf("linking\r\n");
q->next = p->next;
p->next = q;
q->pervious = p;
q->next->pervious = q;
}
4.删除指定节点
void deleteElement(NodePtr paraHeader,char paraChar)
{
NodePtr p,q;
p = paraHeader;
while((p->next!=NULL)&&(p->next->data!=paraChar))
{
p=p->next;
}
if(p->next==NULL)
{
printf("Cannot delete %c\r\n",paraChar);
return;
}
q=p->next;
p->next=p->next->next;
p->next->perivous = p;
free(q);
}
原先
现在
5.测试链表操作
void appendInsertDeleteTest() {
LinkList tempList = initLinkList();
printList(tempList);
appendElement(tempList, 'H');
appendElement(tempList, 'e');
appendElement(tempList, 'l');
appendElement(tempList, 'l');
appendElement(tempList, 'o');
appendElement(tempList, '!');
deleteElement(tempList, 'e');
deleteElement(tempList, 'a');
deleteElement(tempList, 'o');
printList(tempList);
insertElement(tempList, 'o', 1);
printList(tempList);
}