双向链表 (创建、增加、指定插入、去重、删除、输出)循环运行

双向链表(比单项链表好用)

之前写了一份但项链表的学生信息管理的博客,今天又学到了双向链表,所以用双向链表写了一份代码(输入暂时只设置了name项,输出增加了时间),想要其他信息的,可以修改结构体的内容和输入输出对应的内容即可。

本文与原文有很大的不同:

本文中,

链表结点数量无需提前指定,随着内容输入,可以动态增加,不存在输入”溢出“,影响之后的运行输入的问题;

增加了时间函数调用和转换的部分;

双项链表传递参数的时候,会更简洁(使用的参数少)---个人感觉,可能是我之前的单向链表没设计好;

***在指定位置插入,会优先匹配

***如果已经存在 则在其后面开始插入

***如果不存在,那么从头向尾遍历,比较name大小,在第一个比要查入的name大的前面插入

***插入的时候因为调用的是创建or增加的函数,所以插入会再次输入插入name,

***插入数量不限,并且 exit退出

ps:就不上图了,想看效果的,自己复制代码试试吧!

敲黑板:

时间的调用及输出

/*获取时间 年月日时分秒*/ 
void qiandao_t(int *ptim)
{
	int t1,t2,t3;//分别代表 时间 时 分 秒 
 	int td1,td2,td3;//分别代表 时间 时 分 秒
	/*获取时间*/ 
	time_t t;//必备格式 1
	struct tm * lt;//必备格式 2
	time (&t);//获取Unix时间戳。//必备格式 3
	lt = localtime (&t);//转为时间结构。//必备格式 4
	t1=lt->tm_hour,t2= lt->tm_min, t3=lt->tm_sec;
	td1=lt->tm_year+1900,td2= lt->tm_mon+1, td3=lt->tm_mday;
	/*获取的时间数值存入数组*/
	ptim[0]=td1;//年 
	ptim[1]=td2;//月 
	ptim[2]=td3;//日 
	ptim[3]=t1;//时 
	ptim[4]=t2;//分 
	ptim[5]=t3;//秒 
 }

结构体:

struct birthday
{
	int year;
	int month;
	int day;
}; 
struct student
{
	char name[10];
	int sex;
	struct birthday bir;
	int q_time[6];
	struct student *front;//前结点
	struct student *back;//后结点	
};

输入部分

scanf("%s",ex); //把需要输入的内容按格式加进来

输出部分

printf("\n%s  ",p->name);//输出名字
/*输出其他内容,按格式添加在这里即可*/
/*输出时间*/
printf("签到时间:%d年%d月%d日%d时%d分%d秒\n", p->q_time[0],\
		p->q_time[1],p->q_time[2],p->q_time[3],p->q_time[4],p->q_time[5]);

代码如下:

 

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "windows.h"
#include "time.h"
/*结构体定义 出生年月*/
struct birthday
{
	int year;
	int month;
	int day;
}; 
/*结构体定义*/
struct student
{
	char name[10];//姓名
	int Gender;//性别
	struct birthday bir;/*结构体嵌套*/
	int q_time[6];// 时间
	struct student *front;//前结点
	struct student *back;//后结点
	
};
/*函数声明*/
int mean_l();//循环菜单
void qiandao_t(int *ptim); //获取时间函数
void input_creact_lian(struct student *head);//新建or增加结点函数
void output_l(struct student *head);//输出函数 
void del_l(struct student *head);//删除指定结点函数
void Duplicate_removal(struct student *head);//去除重复结点函数
 /*创建链表*/
void input_creact_lian(struct student *head)
 {
 	int i=0; 
 	char ex[10];//接收输入的姓名
 	struct student *q;
 	q=head->front;
 	printf("\n****************增加新的结点***************\n"); 
 	printf("\t       输入 exit 退出!\n\n"); 
 	while(1)
 	{
 		
		scanf("%s",ex); 
		if(strcmp(ex,"exit")==0) break;//退出循环条件
 		struct student *p;
		if((p=(struct student *)malloc((sizeof(struct student))))==NULL)
		{
			printf(" Sorry 分配内存失败。。。");
			exit(0);
		}
		memset(p,0,sizeof(struct student));
		q->back=p;
		p->front=q;
		q=p;
		q->back=NULL;	 
		strcpy(q->name,ex);
		qiandao_t(p->q_time);
		i++;
	}
	q->back=head;/*链接头结点 */ 
	head->front=q;/*链接尾结点 */ 
	printf("\n************恭喜成功创建 %d 个结点***********\n\n",i);//输出结点个数(不含头结点) 
 }
 /*函数输出数据*/
void output_l(struct student *head) 
 {
 	int i=0;
 	if(i==0)printf("\n\n****************最新内容如下******************\n");
	 struct student *p;
 	/*从头结点向后遍历---正序输出*/
 	p=head->back;
 	while(p!=head)
 	{
 		printf("\n%s  签到时间:",p->name);
 		printf("%d年%d月%d日%d时%d分%d秒\n", p->q_time[0],\
		 p->q_time[1],p->q_time[2],p->q_time[3],p->q_time[4],p->q_time[5]);
		p=p->back;
		i++; 
	 }
	 /*从尾结点向前遍历---逆序输出*/
// 	p=head->front;
// 	while(p!=head)
// 	{
// 		printf("\n%s  签到时间:",p->name);
// 		printf("%d年%d月%d日%d时%d分%d秒\n", p->q_time[0],\
//		 p->q_time[1],p->q_time[2],p->q_time[3],p->q_time[4],p->q_time[5]);
//		p=p->front;
//	 }
	printf("\n***************共有 %d 条信息******************\n\n",i);
 }
 /*函数:去除重复结点*/ 
void Duplicate_removal(struct student *head)
 {
 	printf("\n***********即将依据结点name去除重复结点*******\n\n");
 	system("pause");
	printf("\n");
 	int i=0;//删除计数器 
	struct student *p,*q,*dm;
 	/*从头结点向后遍历---正序*/
 	dm=head->back;
	while(dm!=head)
	{
		p=dm->back;
	 	while(p!=head)
	 	{
	 		if(strcmp(p->name,dm->name)==0)
			{
				q=p;
				p=p->back;
				if(i++==0)printf("\n\n****************删除了如下结点****************\n");
				printf("\n%s  签到时间:",q->name);
		 		printf("%d年%d月%d日%d时%d分%d秒\n", q->q_time[0],\
				 q->q_time[1],q->q_time[2],q->q_time[3],q->q_time[4],q->q_time[5]);
				/*舍弃结点*/
				q->front->back=q->back;
		 		q->back->front=q->front;
		 		free(q);
			}
	 		else p=p->back;	
		}
		dm=dm->back;
	}
	printf("\n**************已经完成去重任务*****************\n\n");
 }
 /*函数:删除指定结点*/ 
void del_l(struct student *head)
{
	char ex[10];
	printf("\n请输入要删除的name: ");
	scanf("%s",ex); 
	struct student *p;
 	/*从头结点向后遍历---正序*/
 	p=head->back;
 	while(p!=head)
 	{
 		if(strcmp(p->name,ex)==0)
		{
			q=p;
			p=p->back;
			printf("\n****************删除了如下结点****************\n");
			printf("\n%s  签到时间:",q->name);
	 		printf("%d年%d月%d日%d时%d分%d秒\n", q->q_time[0],\
			 q->q_time[1],q->q_time[2],q->q_time[3],q->q_time[4],q->q_time[5]);
			/*舍弃结点*/
			q->front->back=q->back;
	 		q->back->front=q->front;
	 		free(q);
		}
 		else p=p->back;	
	 }
	 printf("\n****************已经完成删除任务***************\n\n");
}
/*在指定位置插入结点*/
void add_l(struct student *head)
{
	char ex[10];
	printf("\n请输入要插入的name: ");
	scanf("%s",ex); 
	struct student *p,*q;
 	/*从头结点向后遍历---正序*/
 	p=head->back;
 	while(p!=head)
 	{
 		if(strcmp(p->name,ex)==0) //存在 在后面插入 
 		{
 			p=p->back;
 			input_creact_lian(p);
 			break;
		}
 		if(strcmp(p->name,ex)>0)//不存在 找到第一个比插入值大的 在前面插入 
		{	
			input_creact_lian(p);
			break;
		} 
 		else p=p->back;	
	 } 
}
/*获取时间年月日时分秒*/ 
void qiandao_t(int *ptim)
{
	int t1,t2,t3;//分别代表 时间 时 分 秒 
 	int td1,td2,td3;//分别代表 时间 时 分 秒
	/*获取时间*/ 
	time_t t;
	struct tm * lt;
	time (&t);//获取Unix时间戳。
	lt = localtime (&t);//转为时间结构。
	t1=lt->tm_hour,t2= lt->tm_min, t3=lt->tm_sec;
	td1=lt->tm_year+1900,td2= lt->tm_mon+1, td3=lt->tm_mday;
	/*获取的时间数值存入数组*/
	ptim[0]=td1;//年 
	ptim[1]=td2;//月 
	ptim[2]=td3;//日 
	ptim[3]=t1;//时 
	ptim[4]=t2;//分 
	ptim[5]=t3;//秒 
 }
/*循环目录*/
int mean_l(struct student *head)
{
	printf("【0】退出\n【1】新建or增加结点\n【2】插入指定结点\n【3】去除重复结点\n");
	printf("【4】删除指定结点\n【5】查看现有结点\n\n");
	char c;
	printf(" ");
	c=getchar();
	printf("***\n");	
	int i=c-'0';
	switch(i)
	{
		case 0 :  return 0; break;
		case 1 :  input_creact_lian(head); break;
		case 2 :  add_l(head); break;
		case 3 :  Duplicate_removal(head); break;
		case 4 :  del_l(head); break;
		case 5 :  output_l(head); break;
		default :
			printf("****** Err 输入错误。。。*******\n\n");		
	}
	fflush(stdin);
	mean_l(head);
}
/*主函数*/
 int main(void)
 {
	printf("\n************学生签到信息表*************\n\n");
	struct student *head;//创建头结点 
	if((head=(struct student *)malloc((sizeof(struct student))))==NULL)
	{
		printf(" Sorry 分配内存失败。。。");
		exit(0);
	}
	memset(head,0,sizeof(struct student));//初始化头结点 
	head->front=head->back=head;//头结点自循环
	mean_l(head);
	system("pause");
 }

VS 2017 中代码略有不同

如下:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "windows.h"
#include "time.h"
/*结构体定义 出生年月*/
struct birthday
{
	int year;
	int month;
	int day;
};
/*结构体定义*/
struct student
{
	char name[10];//姓名
	int Gender;//性别
	struct birthday bir;/*结构体嵌套*/
	int q_time[6];// 时间
	struct student *front;//前结点
	struct student *back;//后结点

};
/*函数声明*/
int mean_l();//循环菜单
void qiandao_t(int *ptim); //获取时间函数
void input_creact_lian(struct student *head);//新建or增加结点函数
void output_l(struct student *head);//输出函数 
void del_l(struct student *head);//删除指定结点函数
void Duplicate_removal(struct student *head);//去除重复结点函数
 /*创建链表*/
void input_creact_lian(struct student *head)
{
	int  i = 0;
	char ex[10];//接收输入的姓名
	struct student *q;
	q = head->front;
	printf("\n****************增加新的结点***************\n");
	printf("\t       输入 exit 退出!\n\n");
	while (1)
	{

		scanf("%s", ex);
		if (strcmp(ex, "exit") == 0) break;//退出循环条件
		struct student *p;
		if ((p = (struct student *)malloc((sizeof(struct student)))) == NULL)
		{
			printf(" Sorry 分配内存失败。。。");
			exit(0);
		}
		memset(p, 0, sizeof(struct student));
		q->back = p;
		p->front = q;
		q = p;
		q->back = NULL;
		strcpy(q->name, ex);
		qiandao_t(p->q_time);
		i++;
	}
	q->back = head;/*链接头结点 */
	head->front = q;/*链接尾结点 */
	printf("\n************恭喜成功创建 %d 个结点***********\n\n", i);//输出结点个数(不含头结点) 
}
/*函数输出数据*/
void output_l(struct student *head)
{
	int i = 0;
	if (i == 0)printf("\n\n****************最新内容如下******************\n");
	struct student *p;
	/*从头结点向后遍历---正序输出*/
	p = head->back;
	while (p != head)
	{
		printf("\n%s  签到时间:", p->name);
		printf("%d年%d月%d日%d时%d分%d秒\n", p->q_time[0], \
			p->q_time[1], p->q_time[2], p->q_time[3], p->q_time[4], p->q_time[5]);
		p = p->back;
		i++;
	}
	/*从尾结点向前遍历---逆序输出*/
// 	p=head->front;
// 	while(p!=head)
// 	{
// 		printf("\n%s  签到时间:",p->name);
// 		printf("%d年%d月%d日%d时%d分%d秒\n", p->q_time[0],\
//		 p->q_time[1],p->q_time[2],p->q_time[3],p->q_time[4],p->q_time[5]);
//		p=p->front;
//	 }
	printf("\n***************共有 %d 条信息******************\n\n", i);
}
/*函数:去除重复结点*/
void Duplicate_removal(struct student *head)
{
	printf("\n***********即将依据结点name去除重复结点*******\n\n");
	system("pause");
	printf("\n");
	int i = 0;//删除计数器 
	struct student *p, *q, *dm;
	/*从头结点向后遍历---正序*/
	dm = head->back;
	while (dm != head)
	{
		p = dm->back;
		while (p != head)
		{
			if (strcmp(p->name, dm->name) == 0)
			{
				q = p;
				p = p->back;
				if (i++ == 0)printf("\n\n****************删除了如下结点****************\n");
				printf("\n%s  签到时间:", q->name);
				printf("%d年%d月%d日%d时%d分%d秒\n", q->q_time[0], \
					q->q_time[1], q->q_time[2], q->q_time[3], q->q_time[4], q->q_time[5]);
				/*舍弃结点*/
				q->front->back = q->back;
				q->back->front = q->front;
				free(q);
			}
			else p = p->back;
		}
		dm = dm->back;
	}
	printf("\n**************已经完成去重任务*****************\n\n");
}
/*函数:删除指定结点*/
void del_l(struct student *head)
{
	char ex[10];
	printf("\n请输入要删除的name: ");
	scanf("%s", ex);
	struct student *p, *q;
	/*从头结点向后遍历---正序*/
	p = head->back;
	while (p != head)
	{
		if (strcmp(p->name, ex) == 0)
		{
			q = p;
			p = p->back;
			printf("\n****************删除了如下结点****************\n");
			printf("\n%s  签到时间:", q->name);
			printf("%d年%d月%d日%d时%d分%d秒\n", q->q_time[0], \
				q->q_time[1], q->q_time[2], q->q_time[3], q->q_time[4], q->q_time[5]);
			/*舍弃结点*/
			q->front->back = q->back;
			q->back->front = q->front;
			free(q);
		}
		else p = p->back;
	}
	printf("\n****************已经完成删除任务***************\n\n");
}
/*在指定位置插入结点*/
void add_l(struct student *head)
{
	char ex[10];
	printf("\n请输入要插入的name: ");
	scanf("%s", ex);
	struct student *p;
	/*从头结点向后遍历---正序*/
	p = head->back;
	while (p != head)
	{
		if (strcmp(p->name, ex) == 0) //存在 在后面插入 
		{
			p = p->back;
			input_creact_lian(p);
			break;
		}
		if (strcmp(p->name, ex) > 0)//不存在 找到第一个比插入值大的 在前面插入 
		{
			input_creact_lian(p);
			break;
		}
		else p = p->back;
	}
}
/*获取时间年月日时分秒*/
void qiandao_t(int *ptim)
{
	int t1, t2, t3;//分别代表 时间 时 分 秒 
	int td1, td2, td3;//分别代表 时间 时 分 秒
	/*获取时间*/
	time_t t;
	struct tm * lt;
	time(&t);//获取Unix时间戳。
	lt = localtime(&t);//转为时间结构。
	t1 = lt->tm_hour, t2 = lt->tm_min, t3 = lt->tm_sec;
	td1 = lt->tm_year + 1900, td2 = lt->tm_mon + 1, td3 = lt->tm_mday;
	/*获取的时间数值存入数组*/
	ptim[0] = td1;//年 
	ptim[1] = td2;//月 
	ptim[2] = td3;//日 
	ptim[3] = t1;//时 
	ptim[4] = t2;//分 
	ptim[5] = t3;//秒 
}
/*循环目录*/
int mean_l(struct student *head)
{
	printf("【0】退出\n【1】新建or增加结点\n【2】插入指定结点\n【3】去除重复结点\n");
	printf("【4】删除指定结点\n【5】查看现有结点\n\n");
	char c;
	printf(" ");
	c = getchar();
	printf("***\n");
	int i = c - '0';
	switch (i)
	{
	case 0:  exit(0); break;
	case 1:  input_creact_lian(head); break;
	case 2:  add_l(head); break;
	case 3:  Duplicate_removal(head); break;
	case 4:  del_l(head); break;
	case 5:  output_l(head); break;
	default:
		printf("****** Err 输入错误。。。*******\n\n");
	}
	rewind(stdin);//fflush(stdin);在VS中无效
	mean_l(head);
	return 0;//虽然没啥用,但是没有它会警告 没有返回值
}
/*主函数*/
int main(void)
{
	printf("\n************学生签到信息表*************\n\n");
	struct student *head;//创建头结点 
	if ((head = (struct student *)malloc((sizeof(struct student)))) == NULL)
	{
		printf(" Sorry 分配内存失败。。。");
		exit(0);
	}
	memset(head, 0, sizeof(struct student));//初始化头结点 
	head->front = head->back = head;//头结点自循环
	mean_l(head);
	system("pause");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值