您的位置:首页 > 其它

双向循环链表

2013-11-02 21:35 274 查看
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>

//双向循环链表的结构体定义
typedef struct node
{
int data;
struct node *prior;
struct node *next;
}NODE,*PNODE,*LINKLIST;

//初始化
void init(LINKLIST *list)
{
*list = (PNODE)malloc(sizeof(NODE));
(*list)->next = *list;
(*list)->prior = *list;
}

//添加
void add(LINKLIST list,int data)
{
PNODE p=list,q;
q=(PNODE)malloc(sizeof(NODE));//q为要插入的节点
q->data =data;
q->next = p;
q->prior = p->prior;
if(p->prior)
p->prior->next = q;
p->prior = q;
}

//插入 i>=1
void insert(LINKLIST list,int i,int data)
{
PNODE p=list,q;
//将p移动到i-1个位置
while(--i && p->next!=list)
{
p=p->next;
}
assert(i==0);
q = (PNODE)malloc(sizeof(NODE));//q为需要插入的节点
q->data =data;
q->next = p->next;
q->prior = p;
if(p->next)
p->next->prior = q;
p->next = q;
}

//删除
void del(LINKLIST list,int i,int *data)
{
PNODE p=list,q;
//将p移动到第i-1个位置
while(--i && p->next!=list)
{
p=p->next;
}
assert(i==0 && p->next!=list);
q = p->next;//q为要删除的节点
*data = q->data;//将删除的节点的数据域返回
p->next = q->next;//p断开与q连接,和q的后继相连
if(q->next)
q->next->prior = p;//如果删除节点存在后继,那么将这个的prior的指向p
}//end del

//获取双向循环链表的长度
int getLen(LINKLIST list)
{
PNODE p=list;
int i=0;
while((p=p->next)!=list)
{
i++;
}
return i;
}

//获取第i个位置的数据
int getData(LINKLIST list,int i)
{
PNODE p=list;
//将p移动到第i个位置
while(i--)
{
p=p->next;
assert(p!=list);
}
return p->data;
}
//正转一圈输出
void display1(LINKLIST list)
{
PNODE p=list;
while((p=p->next)!=list)
{
printf("%d ",p->data);
}//end while
printf("\n");
}

//正转两圈输出
void display2(LINKLIST list)
{
int count=0;//统计p转到list个数
PNODE p=list;
while(count<2)
{
p=p->next;
if(p==list)
{
count++;
continue;
}else
{
printf("%d ",p->data);
}
}
printf("\n");
}

//反转一圈输出
void display_1(LINKLIST list)
{
PNODE p=list;
while((p=p->prior)!=list)
{
printf("%d ",p->data);
}
printf("\n");
}

//反转两圈输出
void display_2(LINKLIST list)
{
int count=0;//统计p转到list个数
PNODE p=list;
while(count<2)
{
p=p->prior;
if(p==list)
{
count++;
continue;
}else
{
printf("%d ",p->data);
}
}
printf("\n");
}

//销毁
void destroy(LINKLIST *list)
{
PNODE p = *list,q;
while(p->next != *list)
{
q=p->next;
free(p);
p = q;
}
*list = NULL;
}

//显示菜单
void displaymenu()
{
printf("**********这是一个双向循环链表的基本操作程序**********\n");
printf("\t\t\t1,添加\n");
printf("\t\t\t2,插入\n");
printf("\t\t\t3,删除\n");
printf("\t\t\t4,获取长度\n");
printf("\t\t\t5,获取数据\n");
printf("\t\t\t6,正转输出一圈\n");
printf("\t\t\t7,正转输出两圈\n");
printf("\t\t\t8,反转输出一圈\n");
printf("\t\t\t9,反转输出两圈\n");
printf("\t\t\t0,销毁退出\n");
}//end displaymenu

int main()
{
int i,j,choice,flag=1;
LINKLIST list=NULL;
init(&list);//初始化链表
displaymenu();//显示菜单
while(flag)
{
printf("请选择你要的操作:");
scanf("%d",&choice);//输入
switch (choice)
{
case 1:
printf("--你当前选择了添加操作-- (说明:按组合键ctrl+Z并回车可结束添加操作)\n");
while(scanf("%d",&i)!=EOF)
{
add(list,i);
}//end while
printf("--添加操作结束--\n\n");
break;
case 2:
printf("--你当前选择了插入操作--\n");
printf("--请输入插入元素的数据:");
scanf("%d",&j);
printf("--请输入插入位置:");
scanf("%d",&i);
insert(list,i,j);
printf("--插入结束--\n\n");
break;
case 3:
printf("--你当前选择了删除操作--\n");
printf("--请输入删除位置:");
scanf("%d",&i);
del(list,i,&j);
printf("--你删除的元素的数据:%d \n",j);
printf("--删除结束--\n\n");
break;
case 4:
printf("--你当前选择了获取长度操作--\n");
printf("双向循环链表的长度:%d\n",getLen(list));
printf("--获取表长结束--\n\n");
break;
case 5:
printf("--你当前选择了获取数据操作--\n");
printf("--请输入你要获取元素的位置:");
scanf("%d",&i);
printf("第%d个位置的数据为:%d\n",i,getData(list,i));
printf("--获取数据结束--\n");
break;
case 6:
printf("--你当前选择了正转输出一圈操作--\n");
display1(list);
printf("--正转输出一圈操作结束--\n\n");
break;
case 7:
printf("--你当前选择了正转输出两圈操作--\n");
display2(list);
printf("--正转输出两圈操作结束--\n\n");
break;
case 8:
printf("--你当前选择了反转输出一圈操作--\n");
display_1(list);
printf("--反转输出一圈操作结束--\n\n");
break;
case 9:
printf("--你当前选择了反转输出两圈操作--\n");
display_2(list);
printf("--反转输出两圈操作结束--\n\n");
break;
case 0:
printf("--你当前选择了销毁并退出操作--\n");
destroy(&list);//销毁链表
flag=0;//退出循环
printf("--退出操作结束--\n\n");
break;
default:
printf("--你选择错误!\n\n");
break;
}//end switch
}//end while(flag)

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: