双向链表相对于单向链表区别在于双向链表不但保存了下一个节点的地址还保存了上一个的地址,而单向链表只保存了下一个的地址;
这样的话其实双向链表就是一个圆形,固定的头是我们人为设定的
双向链表在排序和查找时候,如果采用从两边开始查找或者排序的需要解决奇偶的问题,再考虑这个问题的时候建议拿出笔在草稿纸上画图。
连接:https://blog.youkuaiyun.com/qq_40082488/article/details/104622519
附上程序:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
typedef struct stu{
int num;
char name[20];
int sorce;
struct stu*p_front;
struct stu*p_next;
}STU;
STU * double_link_inseart(STU*head,STU temp);//双向链表插入
void double_link_printf(STU*head);//双向链表打印
STU *double_link_find(STU*head,char *name);//双向链表的查找
STU *double_link_order(STU *head);//双向链表的排序
int main()
{
STU* head=NULL,*find_temp=NULL,student;
int i;
char find_name[20]="";
for(i=0;i<3;i++)//输入学生信息
{
printf("学生信息:num,name,sorce\n");
scanf("%d %s %d",&student.num,student.name,&student.sorce);
head=double_link_inseart(head,student);
}
double_link_printf(head);//打印输出
printf("-------排序-------\n");
head=double_link_order(head);
double_link_printf(head);
printf("------查找--------\n");
while(1)
{
printf("要查找的学生姓名\n");
scanf("%s",find_name);
find_temp=double_link_find(head,find_name);
printf("%d %s %d\n",find_temp->num,find_temp->name,find_temp->sorce);
}
return 0;
}
//----------------------------------------------------
STU* double_link_order(STU *head)
{
STU *ph,*pt,temp,temp2;
ph=head;//先取出头的地址保存
while(ph->p_front!=head)//标记尾巴,判断头最终位置是否完成一圈
{
pt=ph->p_front;//每次进入都拿头的成员分数进行从尾巴开始比对
while(pt!=head)//从尾巴开始遍历
{
if(head->sorce<pt->sorce)//从大到小排序
{
temp=*head;//先取出头里面的成员
*head=*pt;//再对头重新赋值,前后指向变化了
head->p_front=temp.p_front;//改回原来的指向
head->p_next=temp.p_next;
temp2=*pt;//同上理
*pt=temp;
pt->p_front=temp2.p_front;
pt->p_next=temp2.p_next;
}
pt=pt->p_front;//比对,从尾巴开始往上找
}
head=head->p_next;//每完成一次内循环,头向下移动一个
}
return ph;
}
STU * double_link_inseart(STU*head,STU temp)
{
STU*stu_temp,*p,*pt;
stu_temp=calloc(1,sizeof(STU));//申请空间
*stu_temp=temp;//把要存的内容放入申请的空间
p=head;//把头地址放进P保存
if(head==NULL)//判断链表头有没有数据
{
head=stu_temp;
head->p_next=head;
head->p_front=head;
}else
{//头部之后加节点
pt=p->p_next;//先保存头后面的地址
p->p_next=stu_temp;//再更改头的next
stu_temp->p_front=p;//更改新元素的上一个是头
pt->p_front=stu_temp;//原头的下一个的上一个改为新元素
stu_temp->p_next=pt;//新元素的下一个是上一个头的next
}
return head;
}
void double_link_printf(STU*head)
{
STU *temp;
temp=head;
do{
printf("%d %s %d\n",temp->num,temp->name,temp->sorce);
temp=temp->p_next;
}while(head!=temp);
}
STU *double_link_find(STU*head,char *name)
{
STU *pf;
pf=head->p_front;
while(strcmp(head->name,name)!=0&&strcmp(pf->name,name)!=0&&head!=pf&&head->p_next!=pf)
{
//从两头开始查找,同时判断头尾,并且在奇数情况下不允许相等,在偶数情况下防止死循环
head=head->p_next;
pf=pf->p_front;
}
//处理奇数和偶数的情况
if(strcmp(head->name,name)==0)
{
return head;
}
else if(strcmp(pf->name,name)==0)
{
return pf;
}
return NULL;
}