欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言双向循环链表

程序员文章站 2024-03-22 11:33:34
...

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LINE (struct Student *)

struct Student
{
int num;
float score;
/char name[20];/
struct Student *next;
struct Student *prior;
};

static int n = 0;

struct Student *creat(void) //创建双向循环链表
{
struct Student *head, *p1, *p2;
int i, w;
head = LINE malloc(sizeof(struct Student)); //给head分配内存空间
head->num = 0;
head->score = 0.0; //对head数据进行初始化
head->next = head;
head->prior = head; //head头和尾都指向自己本身
p1 = p2 = head;
printf(“请输入节点个数:\n”);
scanf("%d", &w);
printf("----请输入学号和成绩----\n"); //循环创建节点
for (i = 0; i<w; i++)
{
p1->next = LINE malloc(sizeof(struct Student)); //为p1分配地址空间
scanf("%ld%5f", &p1->next->num, &p1->next->score);
p1 = p1->next; //给p1的赋值
p1->prior = p2; //p1的头部指向p2
p2 = p2->next; //p2尾部指向p1
}
p1->next = head; //p1最后的尾部重新回到head实现循环
head->prior = p1; //head头部指向p1实现双向循环
return head;
}

int getListlength(struct Student *node) //获取链表长度
{
struct Student *length;
int len = 0; //统计链表的节点个数
length = node->next; //length指向第一个节点
while (length != node) //直到length循环链表一圈
{
len++;
length = length->next; //指向下一节点
}
return len; //返回链表长度
}
struct Student *node(struct Student *node, int n) //寻找目标节点
{
struct Student *p;
int i;
p = node;
for (i = 0; i <n; i++)
{
p = p->next; //遍历寻找节点
}
return p; //找到后返回该节点
}

void print_nodeshun(struct Student *head) //顺序输出节点
{
struct Student *p;
p = head->next;
printf("----链表内容输出如下----:\n");
if (head != NULL)
{
do{
printf("%ld,%5.1f\n", p->num, p->score);
//p = p->prior; //指向前一个节点并输出
p = p->next; //指向后一个节点并输出
_sleep(500);
} while (p->num != 0); //循环输出
}
}

void print_nodeni(struct Student *head) //逆序输出节点
{
struct Student *p;
p = head->prior;
printf("----链表内容输出如下----:\n");
if (head != NULL)
{
do{
printf("%ld,%5.1f\n", p->num, p->score);
p = p->prior; //指向前一个节点并输出
//p = p->next; //指向后一个节点并输出
_sleep(500);
} while (p->num != 0);

}

}
void add_node(struct Student *p, int n) //添加节点
{
struct Student *q, *New;
q = node(p, n); //目标节点
New = LINE malloc(sizeof(struct Student)); //为新节点分配空间
printf(“请给新增的节点输入数据:\n”);
scanf("%ld%f", &New->num, &New->score); //新节点输入数据
New->next = q; //新节点的尾部指向原节点
New->prior = q->prior; //新节点的首部指向原节点首部

q->prior->next = New;                                     //原节点的上一节点的next指向新节点
//原节点的上一节点的prior不变

q->prior = New;                                             //原节点prior指向新节点
////原节点next不变

}

void delete_node(struct Student *p, int n) //删除节点
{
struct Student *q;
q = node(p, n); //获取需要删除的节点
q->prior->next = q->next; //该节点的上一节点(next)指向该节点的下一节点
q->next->prior = q->prior; //该节点的下一节点(prior)指向该节点的上一节点

free(q);                                                     //释放该节点所占据的内存

}

void change_node(struct Student *p, int n) //修改节点
{
struct Student *ch;
int num;
float score;
ch = node(p, n); //获取需要修改数据的节点
printf(“该节点目前数据是:\n%ld%5.1f\n”, ch->num, ch->score);
printf(“请输入数据:\n”);
scanf("%ld%f", &num, &score);
ch->num = num; ch->score = score; //将变量的值赋给源节点
printf(“修改后的数据为:\n”);
printf("%ld %5.1f\n", ch->num, ch->score);
}

void find_context(struct Student *p, int n) //查询节点
{
struct Student *q;
q = node(p, n); //获取目标节点
printf(“该节点目前数据是:\n%ld %5.1f\n”, q->num, q->score);
}

int main()
{
struct Student *p;
int a, m, x, h, f, w, leng; //分别表示所用到的输入序号
char cp;
p = NULL;
show:printf("-----------------链表功能展示--------------------\n");
printf("|-----------------------------------------------|\n");
printf("|\t\t1.创建双向循环链表\t\t|\n");
printf("|\t\t2.增加节点\t\t\t|\n");
printf("|\t\t3.删除节点\t\t\t|\n");
printf("|\t\t4.修改节点\t\t\t|\n");
printf("|\t\t5.查询节点\t\t\t|\n");
printf("|\t\t6.显示内容\t\t\t|\n");
printf("|\t\t7.退出\t\t\t\t|\n");
printf("|-----------------------------------------------|\n");
printf("\n");

printf("\t----请输入上述功能序号\n");
scanf("%d", &a);
switch (a)
{
case 1:
	p = creat();
	printf("\t----链表已创建,是否执行其他操作?Y/N\n");
	scanf("%s", &cp);
	if (cp == 'Y' || cp == 'y')
	{
		goto show;
	}
	else
		goto BB;
case 2:
	if (p == NULL){ printf("链表为空,请先创建链表!\n"); goto show; }
add:printf("\t----在第几个节点前插入?\n");
	scanf("%d", &x);
	if (x<1||x > (leng = getListlength(p)) + 1)
	{
		printf("插入的位置不在节点范围内!请重新输入!\n");
		goto add;
	}
	add_node(p, x);
	printf("\t----节点已添加,是否执行其他操作?Y/N\n");
	scanf("%s", &cp);
	if (cp == 'Y' || cp == 'y')
	{
		goto show;
	}
	else
		goto BB;
case 3:
	if (p == NULL){ printf("链表为空,请先创建链表!\n"); goto show; }
det:printf("\t----删除第几个节点?\n");
	scanf("%d", &h);
	if (h<1||h > (leng = getListlength(p)) + 1)
	{
		printf("删除的节点不在范围内!请重新输入!\n");
		goto det;
	}
	delete_node(p, h);
	printf("\t----指定节点已删除,是否执行其他操作?Y/N\n");
	scanf("%s", &cp);
	if (cp == 'Y' || cp == 'y')
	{
		goto show;
	}
	else
		goto BB;
case 4:
	if (p == NULL){ printf("链表为空,请先创建链表!\n"); goto show; }
change:printf("\t----需要修改哪个节点?\n");
	scanf("%d", &f);
	if (f<1||f > (leng = getListlength(p)))
	{
		printf("修改的节点不在范围内!请重新输入!\n");
		goto change;
	}
	change_node(p, f);
	printf("\t----节点已修改完成,是否执行其他操作?Y/N\n");
	scanf("%s", &cp);
	if (cp == 'Y' || cp == 'y')
	{
		goto show;
	}
	else
		goto BB;
case 5:
	if (p == NULL){ printf("链表为空,请先创建链表!\n"); goto show; }
serach:printf("\t----需要查询哪个节点?\n");
	scanf("%d", &m);
	if (m<1||m > (leng = getListlength(p)))
	{
		printf("查询的节点不在范围内!请重新输入!\n");
		goto serach;
	}
	find_context(p, m);
	goto show;
	break;
case 6:
	if (p == NULL){ printf("链表为空\n"); goto show; }
	printf("\t顺序输出请按1,逆序输出请按2\n");
	scanf("%d", &w);
	switch (w)
	{
	case 1:
		print_nodeshun(p); goto show;
	case 2:
		print_nodeni(p); goto show;
	default:goto BB;
	}
	break;
case 7:
BB : printf("\t----感谢使用!----\n"); break;
default:printf("该功能暂未开放!\n"); break;
}
printf("\n");
system("pause");
return 0;

}