#include<stdio.h>
typedef int ElemType;
typedef struct DNode{
ElemType data;
struct DNode *prior,*next;
}DNode, *DLinkList;
//初始化链表,尾插法创建一个双链表
void CreatList(DLinkList *L){
int x;
(*L) = (DLinkList)malloc(sizeof(DNode));
DNode *s,*p=*L;
scanf("%d",&x);
while(x!=999){
s=(DNode *)malloc(sizeof(DNode));
s->data = x;
p->next = s;
s->prior = p;
p = s;
scanf("%d",&x);
}
p->next = NULL;
}
//按序号查找结点值
int GetElem(DLinkList L,int i){
int j = 1;
DNode *p=L->next;
if(i < 1)
{
printf("序号出错。");
}
while(p&&j<i){
p = p->next;
j++;
}
printf("序号%d的值为:%d",i,p->data);
}
//按值查找结点
int LocateElem(DLinkList L,ElemType e){
int i = 1;
DNode *p=L->next;
if(p == NULL)
printf("无此值。");
while(p!=NULL&&p->data!=e){
p = p->next;
i++;
}
printf("值为%d的序号为:%d",e,i);
}
//指定位置插入元素
int ListInsert(DLinkList L,int i,ElemType e){
i--;
int j = 1;
DNode *p = L->next;
if(!p || i<1)
{
printf("序号出错。");
}
while(p&&j<i)
{
p = p->next;
j++;
}
DNode *s = (DLinkList)malloc(sizeof(DNode));
s->data = e;
s->next = p->next;
p->next->prior = s;
s->prior = p;
p->next = s;
return;
}
//指定位置删除元素
int ListDelete(DLinkList L,int i){
i--;
int j = 1;
DNode *p=L->next;
if(i < 1 || !p->next)
{
printf("序号出错。");
}
while(p&&j<i){
p = p->next;
j++;
}
DNode *q = p->next;
p->next = q->next;
q->next->prior = p;
free(q);
return 1;
}
//链表打印
int PrintList(DLinkList L){
DLinkList p = NULL;
p = L->next;
int i = 0;
while(p)
{
printf("%4d",p->data);
p = p->next;
i++;
}
if(i == 0)
{
printf("链表为空。");
}
return 1;
}
//删除链表
int clearList(DLinkList L){
DNode *p = L->next;
while(p)
{
DNode *q = p->next;
free(p);
p = q;
}
L->next = NULL;
return 1;
}
int main(){
int i,e;
DLinkList list;
printf("请输入建立的链表元素(输入999终止): \n");
CreatList(&list);
PrintList(list);
printf("\n请输入要查询的序号:");
scanf("%d",&i);
GetElem(list,i);
printf("\n请输入要查询的元素值:");
scanf("%d",&e);
LocateElem(list,e);
printf("\n请输入需要插入元素的位置及元素值:");
scanf("%d %d",&i,&e);
ListInsert(list,i,e);
PrintList(list);
printf("\n请输入需要删除元素的位置:");
scanf("%d",&i);
ListDelete(list,i);
PrintList(list);
clearList(list);
return 0;
}
1.双链表的引入:
单链表的节点中只有一个指向其后继的指针,这使得单链表只能从头结点依次顺序的向后遍历。若要访问某个结点的
前驱结点(插入、删除操作时),只能从头开始遍历,访问后继结点的时间复杂度为O(1),访问前驱结点的时间复杂度
为O(n)。
为克服单链表以上缺点,引入双链表,双链表指针域中有两个指针prior和next,分别为其前驱结点和后继结点。
2.双链表的主要操作:
双链表仅仅是在单链表的结点增加了一个指向前驱的prior指针,因此,在双链表中执行按序查找和按值查找的操作和单链表
的操作相同;但在插入和删除操作的实现上,需要对prior指针做出修改。
插入操作:
s->next = p->next;
p->next->prior = s;
s->prior = p;
p->next = s;
删除操作:
p->next = q->next;
q->next->prior = p;
free(q);