双向链表操作.docx
《双向链表操作.docx》由会员分享,可在线阅读,更多相关《双向链表操作.docx(17页珍藏版)》请在冰豆网上搜索。
![双向链表操作.docx](https://file1.bdocx.com/fileroot1/2023-3/30/02ebb31c-4100-434e-b0c9-97f491b5c449/02ebb31c-4100-434e-b0c9-97f491b5c4491.gif)
双向链表操作
双向链表的基本运算:
1、查找
假若我们要在一个带表头的双向循环链表中查找数据域为一特定值的某个结点时,我们同样从表头结点往后依次比较各结点数据域的值,若正是该特定值,则返回指向结点的指针,否则继续往后查,直到表尾。
下例就是应用双向循环链表查找算法的一个程序。
#include<stdio.h>
#include<malloc.h>
#defineN10
typedefstructnode
{
charname[20];
structnode*llink,*rlink;
}stud;
stud*creat(intn)
{
stud*p,*h,*s;
inti;
if((h=(stud*)malloc(sizeof(stud)))==NULL)
{
PRintf("不能分配内存空间!
");
exit(0);
}
h->name[0]=’\0’;
h->llink=NULL;
h->rlink=NULL;
p=h;
for(i=0;i<n;i++)
{
if((s=(stud*)malloc(sizeof(stud)))==NULL)
{
printf("不能分配内存空间!
");
exit(0);
}
p->rlink=s;
printf("请输入第%d个人的姓名",i+1);
scanf("%s",s->name);
s->llink=p;
s->rlink=NULL;
p=s;
}
h->llink=s;
p->rlink=h;
return(h);
}
stud*search(stud*h,char*x)
{
stud*p;
char*y;
p=h->rlink;
while(p!
=h)
{
y=p->name;
if(strcmp(y,x)==0)
return(p);
elsep=p->rlink;
}
printf("没有查找到该数据!
");
}
voidprint(stud*h)
{
intn;
stud*p;
p=h->rlink;
printf("数据信息为:
\n");
while(p!
=h)
{
printf("%s",&*(p->name));
p=p->rlink;
}
printf("\n");
}
main()
{
intnumber;
charstudname[20];
stud*head,*searchpoint;
number=N;
clrscr();
head=creat(number);
print(head);
printf("请输入你要查找的人的姓名:
");
scanf("%s",studname);
searchpoint=search(head,studname);
printf("你所要查找的人的姓名是:
%s",*&searchpoint->name);
2、插入
对于双向循环链表,我们现在可以随意地在某已知结点p前或者p后插入一个新的结点。
假若s,p,q是连续三个结点的指针,若我们要在p前插入一个新结点r,则只需把s的右链域指针指向r,r的左链域指针指向s,r的右链域指针指向p,p的左链域指针指向r即可。
在p,q之间插入原理也一样。
下面就是一个应用双向循环链表插入算法的例子:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#defineN10
typedefstructnode
{
charname[20];
structnode*llink,*rlink;
}stud;
stud*creat(intn)
{
stud*p,*h,*s;
inti;
if((h=(stud*)malloc(sizeof(stud)))==NULL)
{
printf("不能分配内存空间!
");
exit(0);
}
h->name[0]=’\0’;
h->llink=NULL;
h->rlink=NULL;
p=h;
for(i=0;i<n;i++)
{
if((s=(stud*)malloc(sizeof(stud)))==NULL)
{
printf("不能分配内存空间!
");
exit(0);
}
p->rlink=s;
printf("请输入第%d个人的姓名",i+1);
scanf("%s",s->name);
s->llink=p;
s->rlink=NULL;
p=s;
}
h->llink=s;
p->rlink=h;
return(h);
}
stud*search(stud*h,char*x)
{
stud*p;
char*y;
p=h->rlink;
while(p!
=h)
{
y=p->name;
if(strcmp(y,x)==0)
return(p);
elsep=p->rlink;
}
printf("没有查找到该数据!
");
}
voidprint(stud*h)
{
intn;
stud*p;
p=h->rlink;
printf("数据信息为:
\n");
while(p!
=h)
{
printf("%s",&*(p->name));
p=p->rlink;
}
printf("\n");
}
voidinsert(stud*p)
{
charstuname[20];
stud*s;
if((s=(stud*)malloc(sizeof(stud)))==NULL)
{
printf("不能分配内存空间!
");
exit(0);
}
printf("请输入你要插入的人的姓名:
");
scanf("%s",stuname);
strcpy(s->name,stuname);
s->rlink=p->rlink;
p->rlink=s;
s->llink=p;
(s->rlink)->llink=s;
}
main()
{
intnumber;
charstudname[20];
stud*head,*searchpoint;
number=N;
clrscr();
head=creat(number);
print(head);
printf("请输入你要查找的人的姓名:
");
scanf("%s",studname);
searchpoint=search(head,studname);
printf("你所要查找的人的姓名是:
%s\n",*&searchpoint->name);
insert(searchpoint);
print(head);
}
更多内容请看C/C++进阶技术文档专题,或
3、删除
删除某个结点,其实就是插入某个结点的逆操作。
还是对于双向循环链表,要在连续的三个结点s,p,q中删除p结点,只需把s的右链域指针指向q,q的左链域指针指向s,并收回p结点就完成了。
下面就是一个应用双向循环链表删除算法的例子:
#include
#include
#include
#defineN10
typedefstructnode
{
charname[20];
structnode*llink,*rlink;
}stud;
stud*creat(intn)
{
stud*p,*h,*s;
inti;
if((h=(stud*)malloc(sizeof(stud)))==NULL)
{
printf("不能分配内存空间!
");
exit(0);
}
h->name[0]=’\0’;
h->llink=NULL;
h->rlink=NULL;
p=h;
for(i=0;i〈n;i++)
{
if((s=(stud*)malloc(sizeof(stud)))==NULL)
{
printf("不能分配内存空间!
");
exit(0);
}
p-〉rlink=s;
printf("请输入第%d个人的姓名",i+1);
scanf("%s",s->name);
s->llink=p;
s->rlink=NULL;
p=s;
}
h->llink=s;
p->rlink=h;
return(h);
}
stud*search(stud*h,char*x)
{
stud*p;
char*y;
p=h->rlink;
while(p!
=h)
{
y=p->name;
if(strcmp(y,x)==0)
return(p);
elsep=p->rlink;
}
printf("没有查找到该数据!
");
}
voidprint(stud*h)
{
intn;
stud*p;
p=h->rlink;
printf("数据信息为:
\n");
while(p!
=h)
{
printf("%s",&*(p->name));
p=p->rlink;
}
printf("\n");
}
voiddel(stud*p)
{
(p->rlink)->llink=p->llink;
(p->llink)->rlink=p->rlink;
free(p);
}
main()
{
intnumber;
charstudname[20];
stud*head,*searchpoint;
number=N;
clrscr();
head=creat(number);
print(head);
printf("请输入你要查找的人的姓名:
");
scanf("%s",studname);
searchpoint=search(head,studname);
printf("你所要查找的人的姓名是:
%s\n",*&searchpoint->name);
del(searchpoint);
print(head);
}
实现一个双向链表,提供如下功能:
1.链表头插入节点;2.链表尾插入节点;3.链表中指定节点后面插入节点.
程序已测试通过,如有疑问再追问,希望对你有帮助
#include
#include
typedefstructdlink{
intdata;
structdlink*prior;//前指针,指向前结点第一个结点prior=NULL
structdlink*next;//后指针,指向后结点最后一个结点next=NULL
}LINK;
voidcrt_dlink(LINK*head,intn)//创建一个带头结点的双向链表,头结点为headn为数据结点个数
{
LINK*tail=head,*p;
inti=0;
for(i=0;i{
p=(LINK*)malloc(sizeof(LINK));//申请一个结点空间
printf("请输入第%2d个结点值:
",i+1);
scanf("%d",&p->data);
tail->next=p;
p->prior=tail;
tail=p;
}
tail->next=NULL;
}
voidshow_dlink(LINK*head)//显示链表
{
LINK*p=head->next;
if(p==NULL)//空表
{
printf("空表\n");
return;
}
printf("正向遍历表:
");
while(p->next)
{
printf("%d->",p->data);
p=p->next;
}
printf("%d\n",p->data);
printf("反向遍历表:
");
while(p!
=head->next)
{
printf("%d->",p->data);
p=p->prior;
}
printf("%d\n\n",p->data);
}
voidappend_dlink(LINK*head,LINK*node)//在表尾增加一个结点
{
LINK*p=head;
while(p->next)//找到尾结点其next=NULL
p=p->next;
p->next=node;//将新结点插入tail后
node->prior=p;//新结点的前结点指向tail结点
node->next=NULL;//新结点的后结点指向NULL
}
voidadd_head_dlink(LINK*head,LINK*node)//在表头增加一个结点
{
LINK*p=head->next;//记录head的下一结点
head->next=node;//将新结点插入head后
node->prior=head;//新结点的前结点指向头结点
node->next=p;//新结点的后结点指向原head的后结点
p->prior=node;//原第一个结点的前结点指向新结点
}
//在指定结点后增加一个结点,
//pos:
指定的第pos个结点
//pos=0时,相当于add_head_dlink()
//pos=max时,相当于append_dlink()
voidinsert_dlink(LINK*head,intpos,LINK*node)
{
inti=0;
LINK*p=head,*pp;
while(i++{
if(!
p->next)//到了表尾
break;//指定的位置超过表长度,追加到表尾
p=p->next;
}
pp=p->next;//记录指定结点的后节点
p->next=node;//新结点插入指定结点后
node->prior=p;//新结点的前结点指向p
node->next=pp;//新结点的后结点指向原p的后结点
if(pp)//当在尾结点插入时,pp=p->next=NULL
pp->prior=node;
}
voidfree_dlink(LINK*head)//释放链表
{
LINK*p=head;
while(p)
{
head=p->next;
free(p);
p=head;
}
}
intmain()
{
LINK*head,*node;
intn=0,pos=0;
head=(LINK*)malloc(sizeof(LINK));//申请头结点空间
head->prior=NULL;
head->next=NULL;
do{
printf("inputnumberofdatan(非0)=");
scanf("%d",&n);
}while(n==0);
crt_dlink(head,n);
show_dlink(head);
node=(LINK*)malloc(sizeof(LINK));
printf("输入新结点的值:
");
scanf("%d",&node->data);
append_dlink(head,node);
show_dlink(head);
node=(LINK*)malloc(sizeof(LINK));
printf("输入新结点的值:
");
scanf("%d",&node->data);
add_head_dlink(head,node);
show_dlink(head);
do{
printf("指定插入位置,负数退出:
");
scanf("%d",&pos);
if(pos<0)
break;
node=(LINK*)malloc(sizeof(LINK));
printf("输入新结点的值:
");
scanf("%d",&node->data);
insert_dlink(head,pos,node);
show_dlink(head);
}while
(1);
free_dlink(head);
system("pause");
return0;
}
用C编写一个函数Create(),该函数可以用于创建一个链表,链表中的结点包括学号、成绩,具有双向指针该函数返回链表的头指针。
1.动态输入学生人数(1-35)
(1)学号:
char型,5位数字,不足5位的前面补0,数字以外时要提示错误信息;
(2)成绩:
short型,最大值100大于100或者小于0或者数字以外时要提示错误信息
2.输入的信息超过相应位数时,只取前面相应位数的信息
/*
学生<1>的学号:
5670
学生<1>的成绩:
999
学生<1>的成绩:
90
0567090
请按任意键继续...
*/
#include
#include
#include
typedefstructnode{
charid[6];
shortscore;
structnode*next;
}*Node,*LinkList;
//去除id中的非数字字符,如果id长度大于slen,只取用前slen个,
//如果不足slen个字符,则在前端添加字符'0'。
char*StId(char*id,intslen){
char*q,*p=id;
inti,len=strlen(id);
for(i=0;p[i];++i){//删除非数字字符
if((p[i]<'0')||(p[i]>'9')){
q=p+i;
while(*q=*(q+1))++q;
--i;
}
}
if(len>=slen)id[slen]='\0';//截取
else{//长度不足则填'0'
for(i=0;i<=len;++i)//往后移动
id[slen-i]=id[len-i];
for(i=0;iid[i]='0';
}
returnid;
}
intStScore(char*s,intmin,intmax){
char*q,*p=s;
inti,num=0;
for(i=0;p[i];++i){//删除非数字字符
if((p[i]<'0')||(p[i]>'9')){
q=p+i;
while(*q=*(q+1))++q;
--i;
}
}
for(i=0;p[i];++i)num=10*num+p[i]-'0';
if((nummax))return-1;
returnnum;
}
LinkListCreateList(intn){//创建单向非循环链表
LinkListhead;
chars[20];
Nodep,q;
head=p=(LinkList)malloc(sizeof(node));
for(inti=0;iq=(LinkList)malloc(sizeof(node));
printf("学生<%d>的学号:
",i+1);
scanf("%s",s);
strcpy(q->id,StId(s,5));
do{
printf("学生<%d>的成绩:
",i+1);
scanf("%s",s);
q->score=StScore(s,0,100);
}while(q->score==-1);
p->next=q;
p=q;
}
p->next=NULL;
returnhead;
}
voidPrintList(LinkListhead){
Nodep=head->next;
while(p){
printf("%s\t%d\n",p->id,p->score);
p=p->next;
}
printf("\n");
}
intmain(){
LinkListhead=CreateList
(1);
PrintList(head);
return0;
}
1、建立一个非空的双向链表,链表的节点要有两个数据域:
1).学生学号2).学生分数;2、遍历双线链表,输出
#include
#include
structtest//结构体
{
unsignedintnumber;
intgrade;
structtest*next;//指向下一个
structtest*previous;//指向上一个
};
voidoutput1(structtest*p)//正顺输出函数
{
while(p)
{
printf("%u\t%d\n",p->number,p->grade);
p=p->next;
}
}
voidoutput2(str