在看Linux源码时,经常会涉及到驱动和设备的匹配,如果想弄清楚匹配过程,就要理解双向循环链表。
这篇文章是理解了Linux的list.h文件后自己的实现应用。
链表的常用的节点操作如下:
增加、删除、查找
首先定义一个结构体,存放学生的信息
struct student {
int number;
char id[20]; //学号
char name[20]; //姓名
float score; //成绩
struct student *next;
struct student *prev;
};
struct student *head = NULL;
/*create head node*/
void init(void)
{
printf("%s\n", __func__);
head = (struct student *)malloc(sizeof(struct student));
head->next = head;
head->prev = head;
}
void add_student(void)
{
/*增加一个学生的信息*/
char new_id[20] = {0};
char new_name[20] = {0};
float new_score = 0.00;
memset(new_id, 0, sizeof(new_id));
memset(new_name, 0, sizeof(new_name));
printf("%s\n", __func__);
printf("enter the id:\n");
scanf("%s", new_id);
/*id是唯一的依据,所以要进行去重操作*/
if(have_same_id(new_id)){
printf("hava same id\n");
goto have_same_id;
}
printf("enter the name:\n");
scanf("%s", new_name);
printf("enter the score:\n");
scanf("%f", &new_score);
/*增加新节点核心操作*/
struct student * new_node = (struct student *)malloc(sizeof(struct student));
struct student * last_node = head->prev;
last_node->next = new_node;
new_node->prev = last_node;
head->prev = new_node;
new_node->next = head;
count++;
/*节点信息填充*/
new_node->number = count;
memset(new_node->id, 0, sizeof(new_node->id));
memset(new_node->name, 0, sizeof(new_node->name));
strcpy(new_node->id, new_id);
strcpy(new_node->name, new_name);
new_node->score = new_score;
printf("add student ok!\n");
list_all_student();
have_same_id:
return ;
}
#define HAVE_SAME_ID 1
#define NO_SAME_ID 0
int have_same_id(char *id)
{
struct student *pos = NULL;
for(pos = head->next; pos != head; pos = pos->next)
{
if(strcmp(pos->id, id) == 0){
return HAVE_SAME_ID;
}
}
return NO_SAME_ID;
}
void delete_student()
{
struct student * pos = NULL;
char id[20];
printf("%s\n", __func__);
memset(id, 0, sizeof(id));
/*以ID为唯一凭证*/
printf("enter the id that you want delete:\n");
scanf("%s", id);
//删除节点核心实现
for(pos = head->next; pos != head; pos = pos->next)
{
if(strcmp(pos->id, id) == 0){
printf("delete\t%d\t%s\t\t\t%s\t\t\t%f\n", pos->number, pos->id, pos->name, pos->score);
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
free(pos);
delete_student_fixed_count(); //删除节点后,修复节点中number标记
return;
}
}
printf("no the same id, pleace check it again\n");
}
void delete_student_fixed_count(void)
{
struct student *pos = NULL;
int i = 0;
count--;
for(pos = head->next, i = 1; pos != head; pos = pos->next, i++)
{
pos->number = i;
}
i--;
if(i != count){
printf("i = %d\t, count = %d\n", i, count);
printf("count error\n");
}
list_all_student();
}
查找结点比较简单,根据一个值遍历所有节点即可
示例代码中,以学生ID为唯一参考
void search_student_score(void)
{
struct student * pos = NULL;
char id[20];
printf("%s\n", __func__);
memset(id, 0, sizeof(id));
printf("enter the id that want to search:\n");
scanf("%s", id);
//核心代码
for(pos = head->next; pos != head; pos = pos->next)
{
if(strcmp(pos->id, id) == 0){
printf("find the id:\n");
printf("\tid\t\t\tname\t\t\tsorce\n");
printf("%d\t%s\t\t\t%s\t\t\t%f\n", pos->number, pos->id, pos->name, pos->score);
return;
}
}
printf("sorry, can not find the id info\n");
}
由于内存空间是使用malloc进行分配的,所有要用free进行手动释放,释放某一个节点比较简单,释放所有节点相对复杂点,其实就是遍历所有节点,并一一删除。
void delete_student()
{
struct student * pos = NULL;
char id[20];
printf("%s\n", __func__);
memset(id, 0, sizeof(id));
printf("enter the id that you want delete:\n");
scanf("%s", id);
//核心实现
for(pos = head->next; pos != head; pos = pos->next)
{
if(strcmp(pos->id, id) == 0){
printf("delete\t%d\t%s\t\t\t%s\t\t\t%f\n", pos->number, pos->id, pos->name, pos->score);
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
free(pos);
delete_student_fixed_count();
return;
}
}
printf("no the same id, pleace check it again\n");
}
结束程序时,要删除所有分配过的内存,防止内存泄漏
该操作就是遍历所有节点并释放内存
void free_all_memory()
{
struct student * pos = head->next;
printf("%s\n", __func__);
for(; pos != head; )
{
head->next = pos->next;
pos->next->prev = head;
printf("\tdelete node->number = %d\n", pos->number); //显示所有要删除的节点,防止有内存泄露
free(pos);
pos = head->next;
}
printf("\tdelete head node\n");
free(head);
}
此示例代码,已经实验过,无内存泄漏,所有功能实现。
/*************************
双向循环链表练习
学生管理系统
2018.01.27
cxiaolei
*************************/
#include
#include
#include
#define HAVE_SAME_ID 1
#define NO_SAME_ID 0
struct student {
int number;
char id[20]; //学号
char name[20]; //姓名
float score;//成绩
struct student *next;
struct student *prev;
};
int count = 0;
struct student *head = NULL;
/*create head node*/
void init(void)
{
printf("%s\n", __func__);
head = (struct student *)malloc(sizeof(struct student));
head->next = head;
head->prev = head;
}
void list_all_student(void)
{
struct student *pos = NULL;
printf("%s\n", __func__);
printf("\n\n\n\tid\t\t\tname\t\t\tsorce\n");
for(pos = head->next; pos != head; pos = pos->next)
{
printf("%d\t%s\t\t\t%s\t\t\t%f\n", pos->number, pos->id, pos->name, pos->score);
}
printf("\n\n\n%s : end\n", __func__);
}
int have_same_id(char *id)
{
struct student *pos = NULL;
for(pos = head->next; pos != head; pos = pos->next)
{
if(strcmp(pos->id, id) == 0){
return HAVE_SAME_ID;
}
}
return NO_SAME_ID;
}
void delete_student_fixed_count(void)
{
struct student *pos = NULL;
int i = 0;
count--;
for(pos = head->next, i = 1; pos != head; pos = pos->next, i++)
{
pos->number = i;
}
i--;
if(i != count){
printf("i = %d\t, count = %d\n", i, count);
printf("count error\n");
}
list_all_student();
}
void add_student(void)
{
char new_id[20] = {0};
char new_name[20] = {0};
float new_score = 0.00;
memset(new_id, 0, sizeof(new_id));
memset(new_name, 0, sizeof(new_name));
printf("%s\n", __func__);
printf("enter the id:\n");
scanf("%s", new_id);
if(have_same_id(new_id)){
printf("hava same id\n");
goto have_same_id;
}
printf("enter the name:\n");
scanf("%s", new_name);
printf("enter the score:\n");
scanf("%f", &new_score);
struct student * new_node = (struct student *)malloc(sizeof(struct student));
struct student * last_node = head->prev;
last_node->next = new_node;
new_node->prev = last_node;
head->prev = new_node;
new_node->next = head;
count++;
new_node->number = count;
memset(new_node->id, 0, sizeof(new_node->id));
memset(new_node->name, 0, sizeof(new_node->name));
strcpy(new_node->id, new_id);
strcpy(new_node->name, new_name);
new_node->score = new_score;
printf("add student ok!\n");
list_all_student();
have_same_id:
return ;
}
void delete_student()
{
struct student * pos = NULL;
char id[20];
printf("%s\n", __func__);
memset(id, 0, sizeof(id));
printf("enter the id that you want delete:\n");
scanf("%s", id);
for(pos = head->next; pos != head; pos = pos->next)
{
if(strcmp(pos->id, id) == 0){
printf("delete\t%d\t%s\t\t\t%s\t\t\t%f\n", pos->number, pos->id, pos->name, pos->score);
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
free(pos);
delete_student_fixed_count();
return;
}
}
printf("no the same id, pleace check it again\n");
}
void search_student_score(void)
{
struct student * pos = NULL;
char id[20];
printf("%s\n", __func__);
memset(id, 0, sizeof(id));
printf("enter the id that want to search:\n");
scanf("%s", id);
for(pos = head->next; pos != head; pos = pos->next)
{
if(strcmp(pos->id, id) == 0){
printf("find the id:\n");
printf("\tid\t\t\tname\t\t\tsorce\n");
printf("%d\t%s\t\t\t%s\t\t\t%f\n", pos->number, pos->id, pos->name, pos->score);
return;
}
}
printf("sorry, can not find the id info\n");
}
void modify_student_score(void)
{
struct student * pos = NULL;
char id[20];
float score = 0.00;
printf("%s\n", __func__);
memset(id, 0, sizeof(id));
printf("enter the id that want to modify:\n");
scanf("%s", id);
printf("enter the score that want to modify:\n");
scanf("%f", &score);
for(pos = head->next; pos != head; pos = pos->next)
{
if(strcmp(pos->id, id) == 0){
printf("find the id and modify the score:\n");
pos->score = score;
printf("\tid\t\t\tname\t\t\tsorce\n");
printf("%d\t%s\t\t\t%s\t\t\t%f\n", pos->number, pos->id, pos->name, pos->score);
return;
}
}
printf("sorry, can not find the id info\n");
}
void free_all_memory()
{
struct student * pos = head->next;
struct student * pos_next = NULL;
printf("%s\n", __func__);
for(; pos != head; )
{
//pos_next = pos->next;
head->next = pos->next;
pos->next->prev = head;
printf("\tdelete node->number = %d\n", pos->number);
free(pos);
pos = head->next;
}
printf("\tdelete head node\n");
free(head);
}
int main(void)
{
int user_select = 0;
init();
printf("简单的学生管理系统");
while(1){
printf("function select\n");
printf("\t1. add a student info\n\t2. delete a student info\n\t3. search student score\n\t4. modify student score\n\t5. list all student\n\t0. quit the application\n");
scanf("%d", &user_select);
switch(user_select){
case 0:{
free_all_memory();
printf("the application will quit\n");
return 0;
}
case 1:{
add_student();
break;
}
case 2:{
delete_student();
break;
}
case 3:{
search_student_score();
break;
}
case 4:{
modify_student_score();
break;
}
case 5:{
list_all_student();
break;
}
default:{
printf("enter error\n");
free_all_memory();
break;
}
}
}
return 0;
}