单链表(带头结点)
头结点保存链表长度和链表的第一个节点的地址,其余增删改查操作相比于不带头结点的单链表更简单。我这里用简单的学生信息系统体现增删改查操作。
-
linklist.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "linklist.h" NODE *create_node(){ NODE *p = (NODE*)malloc(sizeof(NODE)); if(p == NULL){ puts("Error:内存分配失败"); exit(-1); } p->id = 0; p->next = NULL; p->score = 0; return p; } /*尾插录入*/ void create_linklist(F_NODE *const first){ NODE *p = create_node(); while(1){ printf("请输入学号:"); scanf("%d",&p->id); while(getchar()!='\n'); if(linklist_search1(first,p->id) == NULL && p->id > 0){ break; } else{ puts("=>该学生已存在或输入有误,请重新添加"); } } printf("请输入姓名:"); fgets(p->name,32,stdin); char *find = strchr(p->name,'\n'); if(find) *find = '\0'; printf("请输入成绩:"); scanf("%lf",&p->score); while(getchar()!='\n'); if(first->next == NULL){ first->next = p; } else{ /*尾插*/ NODE *find = first->next; while(find->next != NULL) find = find->next; find->next = p; } first->len++; } /*根据学号查找学生*/ NODE* linklist_search1(const F_NODE * first,const int stu_id){ if(first->next == NULL){ return NULL; } NODE *find = first->next; while(find != NULL){ if(find->id == stu_id){ return find; } find = find->next; } /*没有则查找失败*/ return NULL; } /*根据姓名查找学生*/ NODE *linklist_search2(const F_NODE * first,const char *name){ if(first->next == NULL){ puts("=>无任何学生信息"); return NULL; } NODE *find = first->next; while(find != NULL){ if(!strcmp(find->name,name)){ return find; } find = find->next; } /*没有则查找失败*/ return NULL; } /*根据学号删除学生*/ void linklist_delete1(F_NODE *const first,const int stu_id){ NODE *del = linklist_search1(first,stu_id); if(del == NULL){ puts("=>没有该学生"); return; } /*头删*/ if(del == first->next){ first->next = del->next; } else{ /*找到待删除节点的前一个节点*/ NODE *find = first->next; while(find->next != del) find = find->next; find->next = del->next; } free(del); first->len--; } /*根据姓名删除学生*/ void linklist_delete2(F_NODE *const first,const char *name){ NODE *del = linklist_search2(first,name); if(del == NULL){ puts("=>没有该学生"); return; } /*头删*/ if(del == first->next){ first->next = del->next; } else{ /*找到待删除节点的前一个节点*/ NODE *find = first->next; while(find->next != del) find = find->next; find->next = del->next; } free(del); first->len--; } /*修改学生信息*/ void linklist_change(NODE *const search,const int opt){ char *find = NULL; switch(opt){ case 1: printf("输入新的学号:"); scanf("%d",&search->id); while(getchar()!='\n'); break; case 2: printf("输入新的名字:"); fgets(search->name,32,stdin); find = strchr(search->name,'\n'); if(find) *find = '\0'; break; case 3: printf("输入新的成绩:"); scanf("%lf",&search->score); while(getchar()!='\n'); break; } } /*显示所有学生*/ void show_list(const F_NODE *const first){ if(first->next == NULL){ puts("=>无任何学生信息"); return; } else{ NODE *p = first->next; puts("学号\t姓名\t成绩"); while(p != NULL){ printf("%.3d\t%s\t%.1lf\n",p->id,p->name,p->score); p = p->next; } } }
-
linklist_sort.c
#include <stdio.h> #include "linklist.h" NODE *find_max(const F_NODE *const first,const int opt){ NODE *p = first->next; NODE *pmax = p; int max_id = p->id; double max_score = p->score; switch(opt){ case 1: while(p != NULL){ if(max_id < p->id){ max_id = p->id; pmax = p; } p = p->next; } break; case 2: case 3: while(p != NULL){ if(max_score < p->score){ max_score = p->score; pmax = p; } p = p->next; } break; } return pmax; } void move_max(F_NODE *const first,NODE *const pmax){ if(pmax == first->next){ first->next = pmax->next; } else{ NODE *find = first->next; while(find->next != pmax) find = find->next; find->next = pmax->next; } pmax->next = NULL; } /*按学号升序或降序*/ void linklist_sort(F_NODE *const first,const int opt){ NODE *pmax = NULL; NODE *head = NULL; NODE *tail = NULL; while(first->next != NULL){ switch(opt){ case 1: /*从原链表中找出最大节点地址*/ pmax = find_max(first,opt); /*从链表中移出最大节点*/ move_max(first,pmax); /*头插放到无头结点新链表*/ pmax->next = head; head = pmax; break; case 2: /*从原链表中找出最大节点地址*/ pmax = find_max(first,opt); /*从链表中移出最大节点*/ move_max(first,pmax); /*头插放到无头结点新链表*/ pmax->next = head; head = pmax; break; case 3: /*从原链表中找出最大节点地址*/ pmax = find_max(first,opt); /*从链表中移出最大节点*/ move_max(first,pmax); /*尾插放入无头结点链表*/ if(head == NULL){ head = pmax; tail = head; } else{ tail->next = pmax; tail = pmax; } break; } } first->next = head; }
-
fileIO.c
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include "linklist.h" void fileWrite(F_NODE *first){ FILE *fp = fopen("./stu_info.txt","w"); if(fp == NULL){ perror("write"); fclose(fp); exit(-1); } NODE *p = first->next; while(p != NULL){ fprintf(fp,"%d\t%s\t%.1lf\n",p->id,p->name,p->score); p = p->next; } fclose(fp); } int fileRead(F_NODE *first){ FILE *fp = fopen("./stu_info.txt","r"); if(fp == NULL){ perror("write"); exit(-1); } int count = 0; NODE temp; temp.next = NULL; NODE *tail = NULL; while(EOF != fscanf(fp,"%d%s%lf",&temp.id,temp.name,&temp.score)){ NODE *p = create_node(); *p = temp; /*判断链表是否为空*/ if(first->next == NULL){ first->next = p; } else{ tail->next = p; } /*读取个数*/ count++; /*尾指针指向新创建的节点*/ tail = p; } return count; } void progressBar(int n){ /*进度条状态数组*/ char buff[40]; /*字符数组清零*/ memset(buff,'\0',40); /*动态标签*/ char label[] = "\\/\\/"; for(int i = 0;i < 40;i++){ printf("[%-39s][%c][%.1f%%]\r",buff,label[i%4],(i+1)*2.5); /*刷新缓冲区,先将缓冲区已有的内容打印*/ fflush(stdout); buff[i] = '#'; /*等待0.1s(100000us)刷新进度条*/ usleep(n*500+2000); } putchar('\n'); }
-
main.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "menuFrame.h" #include "linklist.h" #include "linklist_sort.h" #include "fileIO.h" int main(){ F_NODE *first = (F_NODE*)malloc(sizeof(F_NODE)); if(first == NULL){ puts("Error:内存申请失败"); exit(-1); } first->next = NULL; int count = fileRead(first); first->len = count; puts("=>读取中..."); progressBar(count); show_list(first); while(1){ mainFrame(); int opt,flag = 1; int stu_id; char name[32],*find; NODE *search = NULL; printf("输入操作选项:"); scanf("%d",&opt); while(getchar()!='\n'); switch(opt){ case 1: create_linklist(first); break; case 2: while(flag){ deleteFrame(); printf("输入选项:"); scanf("%d",&opt); while(getchar()!='\n'); switch(opt){ case 1: flag1: printf("请输入学号:"); scanf("%d",&stu_id); while(getchar()!='\n'); search = linklist_search1(first,stu_id); if(search == NULL){ puts("==>学号不存在"); goto flag1; } else{ linklist_delete1(first,stu_id); puts("==>删除成功"); } break; case 2: flag2: printf("请输入姓名:"); fgets(name,32,stdin); find = strchr(name,'\n'); if(find) *find = '\0'; search = linklist_search2(first,name); if(search == NULL){ puts("==>姓名不存在"); goto flag2; } else{ linklist_delete2(first,name); puts("==>删除成功"); } break; case 0: flag = 0; break; default: puts("==>指令错误"); break; } } break; case 3: while(flag){ printf("请输入学号:"); scanf("%d",&stu_id); while(getchar()!='\n'); search = linklist_search1(first,stu_id); if(search == NULL){ puts("=>没有该学生"); continue; } printf("该学生信息:[学号:%.3d|姓名:%s|成绩:%.1lf]\n",stu_id,search->name,search->score); while(flag){ changeFrame(); printf("请输入选项:"); scanf("%d",&opt); while(getchar()!='\n'); switch(opt){ case 1: linklist_change(search,1); break; case 2: linklist_change(search,2); break; case 3: linklist_change(search,3); break; case 0: flag = 0; break; default: puts("==>指令有误"); break; } } break; } break; case 4: while(flag){ searchFrame(); printf("输入选项:"); scanf("%d",&opt); while(getchar()!='\n'); switch(opt){ case 1: flag3: printf("请输入学号:"); scanf("%d",&stu_id); while(getchar()!='\n'); search = linklist_search1(first,stu_id); if(search == NULL){ puts("==>学号不存在"); goto flag3; } else{ printf("该学生信息:[学号:%.3d|姓名:%s|成绩:%.1lf]\n",stu_id,search->name,search->score); } break; case 2: flag4: printf("请输入姓名:"); fgets(name,32,stdin); find = strchr(name,'\n'); if(find) *find = '\0'; search = linklist_search2(first,name); if(search == NULL){ puts("==>姓名不存在"); goto flag4; } else{ printf("该学生信息:[学号:%.3d|姓名:%s|成绩:%.1lf]\n",search->id,search->name,search->score); } break; case 0: flag = 0; break; default: puts("==>指令错误"); break; } } break; case 5: while(flag){ showFrame(); printf("输入选项:"); scanf("%d",&opt); while(getchar()!='\n'); switch(opt){ case 1: linklist_sort(first,opt); show_list(first); break; case 2: linklist_sort(first,opt); show_list(first); break; case 3: linklist_sort(first,opt); show_list(first); break; case 0: flag = 0; break; default: puts("==>指令有误"); break; } } break; case 0: puts("=>已退出,正在保存..."); progressBar(first->len); fileWrite(first); return 0; } } return 0; }
双向链表(带头结点)
-
头插法创建
/*开辟内存*/ NODE *create_Node(){ NODE *p = (NODE*)malloc(sizeof(NODE)); if(!p){ puts("Error:分配内存失败"); return NULL; exit(-1); } p->data = 0; p->prev = NULL; p->next = NULL; return p; } /*带头结点双链表头插*/ void linklist_create(NODE *head,int data){ NODE *p = create_Node(); p->data = data; /*先连*/ p->next = head->next; p->prev = head; /*后断*/ if(head->next == NULL){ head->next = p; } else{ head->next->prev = p; head->next = p; } head->data++; }
-
查找指定数据
NODE *linklist_search(NODE *head,int data){ NODE *p = head->next; while(p){ if(data == p->data){ return p; } p = p->next; } return NULL; }
-
删除指定数据节点
void linklist_delete(NODE *head){ int data; printf("输入删除的数据:"); scanf("%d",&data); while(getchar()!='\n'); NODE *find = linklist_search(head,data); if(find){ find->prev->next = find->next; if(find->next){ find->next->prev = find->prev; } find->next = NULL; find->prev = NULL; free(find); head->data--; } else{ puts("=>删除失败"); } }
-
数据排序(升序)
NODE *find_min(NODE *head){ NODE *p = head->next; NODE *pmin = p; for(int i = 0;i < head->data;i++){ if(p->data < pmin->data){ pmin = p; } p = p->next; } head->data--; return pmin; } void move_min(NODE *head,NODE *pmin){ pmin->prev->next = pmin->next; if(pmin->next){ pmin->next->prev = pmin->prev; } pmin->prev = NULL; pmin->next = NULL; } void insert_min(NODE *head,NODE *pmin){ NODE *find = head; while(find->next != NULL) find = find->next; find->next = pmin; pmin->prev = find; } void linklist_sort(NODE *head){ if(!head->next){ return; } int len = 0; while(head->data){ NODE *pmin = find_min(head); move_min(head,pmin); /*尾插到原链表最后*/ insert_min(head,pmin); len++; } head->data = len; }
-
释放链表
void linklist_free(NODE **head){ if((*head)->next){ linklist_free(&(*head)->next); free((*head)->next); } *head = NULL; }