头指针双向循环链表实现学生信息统计

main.c
实现之后才发现,头节点和头指针实际上差了很多。头节点可以直接解决的事,用头指针的时候添加删除,销毁都要考虑头指针的指向变化问题,不得不在函数中使用到二级指针,直接考虑很难想到,排查bug真让人头疼,不过最后发现这很有趣。
准备准备,学完图形的库,考虑写个小窗口环境出来,
这次的实现并没有同系统中的文件关联,
fopen,fgets fputs fclose都很有趣,
#include<stdio.h>
#include<stdlib.h>
#include"student.h"
int main(int argc, const char *argv[])
{
	int button;
	CL p= NULL;
	for(;;)
	{
		menu();
		scanf("%d",&button);
		while(button>6 ||button <1)
		{
			printf("\t\t指令错误,请重新输入:");
			scanf("%d",&button);
		}
		switch(button)
		{
		case 1:
			insert(&p);
			if(NULL == p)
			{
				return -1;
			}
			break;
		case 2:
			insert(&p);
			break;
		case 3:
			show(p);
			break;
		case 4:
			search(p);
			break;
		case 5:
			destory(&p);
			break;
		case 6:
			return 0;
		}
	}

	return 0;
}

student.h

#ifndef __STUDENT_H__
#define __STUDENT_H__

//定义学生结构体类型
	typedef struct student{
		int age;
		char name[20];
		int score;
	}stu;
typedef struct class{
	stu mate;
	struct class *prio;
	struct class *next;
}Class,*CL;


//遍历
void show(CL);
//添加函数
CL insert(CL*);
//查询
void search(CL);
//删除
CL destory(CL *p);
void menu();
#endif

student.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"student.h"

//遍历
void show(CL p)
{
	if(NULL == p)
	{
		printf("\t\t%s 班级为空\n",__FUNCTION__);
		return ;
	}
	CL q = p;
	printf("\t====================================\n");
	printf("\t\t姓名\t学号\t分数\n");
	do{
		printf("\t\t%s\t%d\t%d\n",q->mate.name,q->mate.age,q->mate.score);
		q = q->next;
	}while(q != p);
}
//添加函数
CL insert(CL *p)
{
	int age,score;
	char name[30] = "";
	//判断班级是否为空,若空,则申请节点,上传信息,返回班级指针
	if(NULL == *p)
	{
		printf("班级为空,开始添加学生信息\n");
		CL head = (CL)malloc(sizeof(Class));
		if(NULL == head)
		{
			printf("\t\t%s 空间申请失败\n",__FUNCTION__);
			return NULL;
		}
		printf("\t\t请分别输入学生信息\n");
		printf("\t\t姓名:__________\b\b\b\b\b\b\b\b\b\b");
		scanf("%s",name);
		printf("\t\t学号:___\b\b\b");
		scanf("%d",&age);
		printf("\t\t成绩:___\b\b\b");
		scanf("%d",&score);
		head->mate.age = age;
		head->mate.score = score;
		strcpy(head->mate.name,name);
		head->next = head;
		head->prio = head;
		*p = head;
		return head;
	}
	//头插
	CL insert = (CL)malloc(sizeof(Class));
	if(NULL == insert)
	{
		printf("\t\t%s 空间申请失败\n",__FUNCTION__);
		return NULL;
	}
	printf("\t\t请分别输入学生信息\n");
	printf("\t\t姓名:__________\b\b\b\b\b\b\b\b\b\b");
	scanf("%s",name);
	printf("\t\t学号:___\b\b\b");
	scanf("%d",&age);
	printf("\t\t成绩:___\b\b\b");
	scanf("%d",&score);
	insert->mate.age = age;
	insert->mate.score = score;
	strcpy(insert->mate.name,name);
	insert->next = (*p);
	insert->prio =(*p)->prio;
	(*p)->prio->next = insert;
	(*p)->prio = insert;
	*p = insert;
	return *p;
}
//查询
void search(CL p)
{
	if(NULL == p)
	{
		printf("\t\t%s 班级为空\n",__FUNCTION__);
		return ;
	}
	int tag;
	printf("\t\t请选择查询方式:\n\t\t1:查询学号\n\t\t2:查询姓名\n\t\t3:查询成绩\n");
	printf("\t\t请输入选择方式对应的序号<1 OR 2 OR 3>: _\b");
	scanf("%d",&tag);
	while(tag<1 || tag>3)
	{
		printf("输入有误,请重新输入\n");
		while(getchar());
		scanf("%d",&tag);
	}
	CL q = p;
	int num,sc;
	int FLAG = 0;
	char buffer[30] = "";
	switch(tag)
	{
	case 1:
		{
			printf("\t\t请输入要查询的学号:__\b\b");
			scanf(" %d",&num);
			do{
				if(num == q->mate.age)
				{
					printf("\t\t姓名:%s__学号:%d__成绩:%d\n",q->mate.name,q->mate.age,q->mate.score);
					FLAG = 1;
				}
				q = q->next;
			}while(q != p);
			if(0 == FLAG)printf("\t\t查无此人\n");
			break;
		}
	case 2:
		{
			printf("\t\t请输入要查询的姓名:");
			scanf(" %s",buffer);
			do{
				if(!strcmp(buffer,q->mate.name))
				{
					printf("\t\t姓名:%s__学号:%d__成绩:%d\n",q->mate.name,q->mate.age,q->mate.score);
					FLAG = 1;
				}
				q = q->next;
			}while(q != p);
			if(0 == FLAG)printf("\t\t查无此人\n");
			break;
		}
	case 3:
		{
			printf("\t\t请输入要查询的成绩:");
			scanf(" %d",&sc);
			do{
				if(sc == q->mate.score)
				{
					printf("\t\t姓名:%s__学号:%d__成绩:%d\n",q->mate.name,q->mate.age,q->mate.score);
					FLAG = 1;
				}
				q = q->next;
			}while(q != p);
			if(0 == FLAG)printf("\t\t查无此人\n");
			break;
		}
	}
}
CL destory(CL *p)
{
	if(NULL == *p)
	{
		printf("\t\t%s 班级为空\n",__FUNCTION__);
		return NULL;
	}
	int num = 0;
	printf("\t\t请输入要删除学生的学号:____\b\b\b\b");
	scanf("%d",&num);
	CL q = (*p);
	do{
		if(num == q->mate.age)
		{
			if(q->next == q)
			{
				free(q);
				(*p) = NULL;
				q = NULL;
			printf("删除成功\n");
				return NULL;
			}
			if(q == (*p))
			{
				(*p) = q->next;
				q->prio->next = (*p);
				free(q);
				q = NULL;
			printf("删除成功\n");
				return *p;
			}
			q->next->prio = q->prio;
			q->prio->next = q->next;
			free(q);
			q = NULL;
			printf("删除成功\n");
			return *p;
		}
		q = q->next;
	}while(q != *p);
	printf("\t\t查无此人\n");
}
void menu()
{
	printf("\t============================================================\n");
	printf("\t====================--------------------====================\n");
	printf("\t====================| 学生信息管理系统 |====================\n");
	printf("\t====================--------------------====================\n");
	printf("\n");
	printf("\t\t\t\t1:创建班级成员\n");
	printf("\t\t\t\t2:添加学生\n");
	printf("\t\t\t\t3:查看学生信息\n");
	printf("\t\t\t\t4:查找对应学生\n");
	printf("\t\t\t\t5:删除学生信息\n");
	printf("\t\t\t\t6:退出菜单\n");
	printf("\n");
	printf("\t请输入要执行的对应操作:");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java实现带头双向循环链表的完整源码,供参考: ``` public class DoublyCircularLinkedList<T> { private Node<T> head; // 头节点 // 节点类 private static class Node<T> { T data; Node<T> prev; Node<T> next; Node(T data) { this.data = data; this.prev = null; this.next = null; } } // 构造函数 public DoublyCircularLinkedList() { head = new Node<>(null); head.prev = head; head.next = head; } // 在链表末尾添加元素 public void add(T data) { Node<T> node = new Node<>(data); node.prev = head.prev; node.next = head; head.prev.next = node; head.prev = node; } // 在指定位置插入元素 public void insert(int index, T data) { Node<T> node = new Node<>(data); Node<T> p = head.next; int i = 0; while (p != head && i < index) { p = p.next; i++; } if (p == head || i > index) { throw new IndexOutOfBoundsException(); } node.prev = p.prev; node.next = p; p.prev.next = node; p.prev = node; } // 删除指定位置的元素 public void remove(int index) { Node<T> p = head.next; int i = 0; while (p != head && i < index) { p = p.next; i++; } if (p == head || i > index) { throw new IndexOutOfBoundsException(); } p.prev.next = p.next; p.next.prev = p.prev; p.prev = null; p.next = null; } // 获取指定位置的元素 public T get(int index) { Node<T> p = head.next; int i = 0; while (p != head && i < index) { p = p.next; i++; } if (p == head || i > index) { throw new IndexOutOfBoundsException(); } return p.data; } // 获取链表长度 public int size() { Node<T> p = head.next; int size = 0; while (p != head) { size++; p = p.next; } return size; } } ``` 该代码实现了带头双向循环链表数据结构,支持在链表末尾添加元素、在指定位置插入元素、删除指定位置的元素、获取指定位置的元素、获取链表长度等操作。在算法实现中,通过一个Node类来表示链表中的节点,包含数据域、前驱指针和后继指针。同时,链表的头节点也是一个Node对象,通过头节点来连接链表的首尾,形成双向循环链表

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值