c语言双向循环链表存储长整型,C语言实现双向循环链表功能(增加文件读写链表功能)...

双向链表其实是单链表的改进。当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。在c语言中双向链表结点类型可以定义为:typedef struct node{int data; /*数据域*/struct node *llink,*rlink; /*链域,*llink是左链域指针,*rlink是右链域指针*/}JD;当然,也可以把一个双向链表构建成一个双向循环链表。双向链表与单向链表一样,也有三种基本运算:查找、插入和删除。

1、查找假若我们要在一个带表头的双向循环链表中查找数据域为一特定值的某个结点时,我们同样从表头结点往后依次比较各结点数据域的值,若正是该特定值,则返回指向结点的指针,否则继续往后查,直到表尾。

2、插入对于双向循环链表,我们现在可以随意地在某已知结点p前或者p后插入一个新的结点。假若s,p,q是连续三个结点的指针,若我们要在p前插入一个新结点r,则只需把s的右链域指针指向r,r的左链域指针指向s,r的右链域指针指向p,p的左链域指针指向r即可。在p,q之间插入原理也一样。

3、删除删除某个结点,其实就是插入某个结点的逆操作。还是对于双向循环链表,要在连续的三个结点s,p,q中删除p结点,只需把s的右链域指针指向q,q的左链域指针指向s,并收回p结点就完成了。

4、保存和读写

在实际应用中,如通讯录系统,需要保存的联系人的信息,那么就需要将链表的数据保存在文件中,如果需要对通讯录内容进行更改或者操作就需要先从文件中读取之前保存的链表的数据,然后进行修改。(使用fread,fwrite,stat即可实现读写的功能)

下面使用具体的例子演示双向循环链表的实现,并将链表的数据保存在文件中。

#include

#include

#include

#include

typedef struct node{

char name[32];

struct node *l;//左节点

struct node *r;//右节点

}no;

unsigned int len=sizeof(no);

no* CreateList(int n){

no *head,*cur,*prev;

if((head=(no *)malloc(len))==NULL){

printf("Alloc Failed \n");

return NULL;

}

head->name[0]='H';

head->l=NULL;

head->r=NULL;

prev=head;

for(n;n>=1;n--){

if((cur=(no *)malloc(len))==NULL){

printf("Alloc Failed \n");

return NULL;

}

prev->r=cur;

printf("pls input the name:");

scanf("%s",cur->name);

cur->l=prev;

cur->r=NULL;

prev=cur;

}

prev->r=head;

head->l=cur;

return head;

}

void PrintList(no *head){

no *cur;

cur=head->r;

while(cur!=head){

printf("[%s]",cur->name);

cur=cur->r;

}

printf("\n");

}

no *Search(no* head){

no *cur;

char *name;

cur=head->r;

printf("pls input search name:");

scanf("%s",name);

while(cur!=head){

if(strcmp(name,cur->name)==0)

return cur;

else{

cur=cur->r;

}

}

printf("Search : Not Found\n");

return NULL;

}

void* InsertNode(no *cur){//在cur节点之后插入

no *insert;

char *str;

if((insert=(no *)malloc(len))==NULL){

printf("Alloc Failed \n");

return NULL;

}

printf("pls input insert name:");

scanf("%s",insert->name);

insert->r=cur->r;

insert->l=cur;

cur->r=insert;

cur->r->l=insert;

}

void DeleteNode(no *cur){//删除cur节点

(cur->r)->l=cur->l;

(cur->l)->r=cur->r;

free(cur);

cur=NULL;

}

FILE* File_CreateKeepOpen(char *filename,char* mode){

FILE *fp;

fp=fopen(filename,mode);

if(!fp){

return NULL;

}

return fp;

}

int File_Close(FILE *fp){

if(!fclose(fp))

return 1;

else

return 0;

}

int File_SaveNodeData(FILE *fp,no *head){

no *cur;

int size;

cur=head->r;

while(cur!=head){

size=fwrite(cur,len,1,fp);

cur=cur->r;

size+=size;

}

return size;

}

no* File_ReadNodeData(FILE *fp){//其实就是创建双向循环链表的过程

no *head,*cur,*prev;

struct stat s;

int size,n;

stat("list.data",&s);

printf("s.st_size[%d]\n",s.st_size);

printf("node num [%d]\n",s.st_size/len);

if((head=(no *)malloc(len))==NULL){

printf("Alloc Failed \n");

return NULL;

}

head->name[0]='H';

head->l=NULL;

head->r=NULL;

prev=head;

for(n=1;n<=s.st_size/len;n++){

if((cur=(no *)malloc(len))==NULL){

printf("Alloc Failed \n");

return NULL;

}

prev->r=cur;

size=fread(cur,1,len,fp);

cur->l=prev;

cur->r=NULL;

prev=cur;

}

prev->r=head;

head->l=cur;

return head;

}

int main(){

no *head,*cur,*ret;

no *File_head;

FILE *fp;

int n;

do{//使用do{}while结构实现scanf循环读取数据

printf("pls input create list num(integer) : ");

scanf("%d",&n);

}while(getchar()!='\n');//getchar执行之后消除缓冲区

if((head=CreateList(n))!=NULL)

PrintList(head);

else

printf("CreateList Failed\n");

cur=Search(head);

if((ret=InsertNode(cur))!=NULL)

PrintList(head);

else

printf("InsertNode Failed\n");

cur=Search(head);

DeleteNode(cur);

PrintList(head);

/*以只写的方式创建并打开文件,将以head为首节点的链表数据保存在文件list.data中*/

fp=File_CreateKeepOpen("list.data","w");

if(!fp){

printf("File_CreateKeepOpen Failed\n");

return -1;

}

/*将以head为首节点的链表数据保存在文件list.data中*/

size=File_SaveNodeData(fp,head);

/*关闭文件list.data*/

if(!File_Close(fp)){

printf("File_Close Failed\n");

return -1;

}

/*以只读的方式打开文件list.data*/

fp=File_CreateKeepOpen("list.data","r");

if(!fp){

printf("File_CreateKeepOpen Failed\n");

return -1;

}

/*从文件list.data中读取链表数据,并返回新的链表头节点File_head*/

File_head=File_ReadNodeData(fp);

if(File_head!=NULL){

printf("File_ReadNodeData Result:");

PrintList(File_head);

}

/*关闭文件list.data*/

if(!File_Close(fp)){

printf("File_Close Failed\n");

return -1;

}

/*根据新的链表头File_head,插入新的数据并打印*/

cur=Search(File_head);

if((ret=InsertNode(cur))!=NULL)

PrintList(File_head);

else

printf("InsertNode Failed\n");

return 0;

}

以下是测试过程:

0818b9ca8b590ca3270a3433284dd417.png

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值