注意事项:
- 双向链表的头结点的prior指向最后的结点。最后一个结点的next指向头结点
- 在初始化链表时,前驱后继指针均指向头结点。
- 双向链表是循环链表的一个扩充。但是使用的是头结点。
#include<stdio.h>
#include<stdlib.h>
typedef struct DuLNode
{
int data;
struct DuLNode *prior, *next;
}DuLNode, *DuLinkList;
DuLinkList Creat() //正序,尾插
{
DuLinkList L = (DuLinkList)malloc(sizeof(DuLNode));
L->next = L->prior = L;
L->data = -1;
printf("Please enter the number:\n");
int n;
scanf_s("%d", &n);
printf("the number:\n");
DuLinkList q = L; //需要一个指针作为建立链表时表示其前一个结点。
for (int i = 0; i < n; i++)
{
DuLinkList p = (DuLinkList)malloc(sizeof(DuLNode));
scanf_s("%d", &p->data);
p->next = L;
q->next = p;
p->prior = q;
q = p;
}
return L;
}
void Destroy(DuLinkList L)//实际上是clearlist不销毁链表,如果销毁需要把头结点一起释放
{
DuLinkList q;
q = L->next;
while (q != L)
{
q = q->next;
free(q->prior);
}
L->next = L->prior = L;
}
void Insert(DuLinkList L, int val, int index)
{
DuLinkList q, p;
p = (DuLinkList)malloc(sizeof(DuLNode));
p->data = val;
q = L->next;
int i = 1;
while (q != L && i < index - 1)
{
i++;
q = q->next;
}
p->next = q->next;
q->next->prior = p;//这里需要注意一下,需要把新插入的结点的后一个结点指向新节点
q->next = p;
p->prior = q;
}
void Delete(DuLinkList L, int index)
{
DuLinkList q = L->next;
int i = 1;
while (q != L && i < index)//这里找到第i个结点而不是i-1个
{
i++;
q = q->next;
}
q->prior->next = q->next;//这里运用了双向链表的优势
q->next->prior = q->prior;//不需要额外一个指针指向前一个
free(q);
}
void Traverse(DuLinkList L)
{
DuLinkList q = L->next;
while (q != L)
{
printf("%d->", q->data);
q = q->next;
}
printf("NULL\n");
}
int main()
{
DuLinkList L = Creat();
Traverse(L);
Insert(L, 5, 3);
Traverse(L);
Delete(L, 3);
Traverse(L);
Destroy(L);
Traverse(L);
}