题目:
双向链表是在结点中既保存了后一个结点指针又保存了前一个结点指针的链表。这种链表较单向链表而言能够快速查找某一结点的前后结点。
输入
输入数据只有一组,包含很多行。每行有1~3个整数。第一个整数如果是0,则表示输出双向链表中的所有元素;第一个整数如果是1,表示插入1个整数,其后跟2个整数i、e代表在第i个位置插入e;第一个整数如果是2,表示删除1个整数,其后跟1个整数i,表示删除的位置为i。
起始双向链表为空表。保证链表中每个元素不会重复,同时所有的操作都合法。输出
当需要输出双向链表中的所有元素时输出,每次输出一行。整数间用一个空格隔开。
分析:
双向链表与单链表基本类似,只是在定义链表结构体时增设了一个前指针prior,此外在基础的增删查改功能时,也需根据需求对这其两个指针做相应变换。
代码:
#include<stdio.h>
#include<stdlib.h>
//建立双向链表
typedef struct DuLNode
{
int data;
struct DuLNode *prior;
struct DuLNode *next;
}DuLNode,*DuLinkList;
void ListCreate_DuL(DuLinkList L)
{
L->prior=L;
L->next=L;
}
//从双向链表中获取某个结点
DuLNode * GetElem_DuL(DuLinkList L,int i)
{
DuLNode *p=L->next;
int j=1;
while(p!=L&&j<i){
p=p->next;
++j;
}
if(p==L&&j<i) { //获取失败返回空
printf("Get Fail!!\n");
return NULL;
}
return p;
}
//双向链表的插入(在i之前插入)
void ListInsert_DuL(DuLinkList L,int i,int e)
{
DuLNode *p,*s;
p = GetElem_DuL(L, i); // 获取第i个元素的位置指针
if (!p) return; // 如果p为NULL,说明位置不合法,返回
s = (DuLinkList) malloc(sizeof(DuLNode));
s->data=e;
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prior=s;
}
//双向链表的删除
void ListDelete_DuL(DuLinkList L,int i,int e)
{
DuLNode *p;
p=GetElem_DuL((L),i);//获取第i个元素的位置指针
if(!p) return;
e=p->data;
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);
p=NULL;
}
//链表打印函数
void Pint_DuL(DuLinkList L)
{
DuLNode *p=L->next;
while(p!=L){
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
int main(){
DuLinkList L=NULL;
L=(DuLinkList ) malloc(sizeof(DuLNode));
ListCreate_DuL(L);
int n,a,e;
while(scanf("%d",&n)!=EOF)
{
if(n==1)
{
scanf("%d%d",&a,&e);
ListInsert_DuL(L,a,e);
}
else if(n==2)
{
scanf("%d",&a);
ListDelete_DuL(L,a,e);
}
else if(n==0)
{
Pint_DuL(L);
}
}
return 0;
}
测试:
样例输入
1 1 2 0 1 2 7 0 2 1 0 1 2 4 1 3 5 1 2 6 0 2 3 0
样例输出
2 2 7 7 7 6 4 5 7 6 5