- 项目名称
Link_List
- 文件
head.h
#ifndef LINK_LIST_HEAD_H
#define LINK_LIST_HEAD_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef enum _gender_ {man, women} Gender; // 性别
typedef struct std {
int ID; // ID
char name[21]; // 姓名
Gender gender; // 性别
int age; // 年龄
struct std* next; // 下一个节点
} Std;
Std* Link_created(void); // 创造链表
bool Link_input(Std* index_Std); // 输入链表中一个节点的内容
bool Link_output(Std* index_Std); // 输出链表中一个节点的内容
bool Link_input_check(void); // 检查是否继续输入(用于构建和添加)
bool Link_malloc(Std** p, int len); // 向p指针内分配len个节点的内存
Std* Link_search(Std* head, int index_ID); // 根据ID查找节点 若找不到则返回NULL(ID必须唯一)
Std* Link_before(Std* head, int index_ID); // 返回前一节点 若没有则返回NULL
Std* Link_after(Std* head, int index_ID); // 返回后一节点 若没有则返回NULL
bool Link_insert_ID_bef(Std** head, int index_ID); // 在对应ID的节点的前面插入节点
bool Link_insert_ID_aft(Std* head, int index_ID); // 在对应ID的节点的后面插入节点
bool Link_insert_Std_bef(Std** head, Std* index_Std); // 在对应节点的前面插入节点
bool Link_insert_Std_aft(Std* head, Std* index_Std); // 在对应节点的后面插入节点
bool Link_delete_ID(Std** head, int index_ID); // 删除对应ID的节点
bool Link_delete_name(Std** head, char* index_name); // 删除所有具有对应姓名的节点
bool Link_delete_gender(Std** head, Gender index_gender); // 删除所有具有对应性别的节点
bool Link_delete_age(Std** head, int index_age); // 删除所有具有对应年龄的节点
bool Link_delete_Std(Std** head, Std* index_Std); // 删除对应节点
bool Link_free(Std* head); // 释放整个链表的内存
bool Link_add_head(Std** head); // 在链表的头部添加一系列节点
bool Link_add_end(Std* end); // 在链表的尾部添加一系列节点
bool Link_display(Std* head); // 打印链表内容
bool Link_display_name(Std* head); // 打印链表内所有的姓名
bool Link_reversal(Std** head); // 反转链表
int Link_get_ID(Std* index_Std); // 获得节点的ID
char* Link_get_name(Std* index_Std); // 获得节点的姓名
Gender Link_get_gender(Std* index_Std); // 获得节点的性别
int Link_get_age(Std* index_Std); // 获得节点的年龄
bool Link_next(Std** index_Std); // 指向下一个节点
bool Link_arrange_ID(Std* head); // 根据ID排序
bool Link_linked(Std* head, Std* end); // 连接节点
bool Link_swap(Std* a, Std* b); // 交换节点的内容
bool Link_copy_all(Std* dest, Std* src); // 复制节点的所有内容(包含next)
bool Link_copy_value(Std* dest, Std* src); // 复制节点的内容(不包含next)
#endif //LINK_LIST_HEAD_H
main.c
#include "head.h"
int main()
{
#if false
/* test1 */ {
Std* test = Link_created();
printf("\n\nNow input another.\n\n");
Std* det = Link_created();
Link_display(test);
printf("Display end.\n\n");
while (det != NULL) {
Link_delete_age(&test, Link_get_age(det));
det = det->next;
}
Link_display(test);
printf("Display end.\n\n");
Link_free(test);
} // 此处测试可演示作业2
/**
* 建立一个链表
* 每个节点包括:学号,姓名,性别以及年龄
* 输入一个链表
* 如果链表中的节点所包含的年龄等于此年龄,则将此节点删去
*/
/**
* 1. Created
* 2. Malloc
* 3. Input
* 4. Input Check
* 5. Next
* 6. Display
* 7. Output
* 8. Free
* 9. Get Age
* 10. Delete Age
*/
#endif
#if false
/* test2 */ {
Std* test = Link_created();
Link_display(test);
printf("Display end.\n\n");
Link_reversal(&test);
Link_display(test);
printf("Reversal end.\n\n");
Link_free(test);
} // 此处测试可演示作业3
/**
* 通过指针将单链表直接倒序
* (不声明新链表或者数组)
* (这个题搞懂了,链表这块就没什么大问题了)
*/
/**
* 1. Reversal
*/
#endif
#if false
/* test3 */ {
Std* test = Link_created();
Link_display(test);
printf("Display end.\n\n");
Std* ret = Link_search(test, 2);
Link_output(ret);
printf("Search end.\n\n");
Std* before = Link_before(test, ret->ID);
Link_output(before);
printf("Before end.\n\n");
Std* after = Link_after(test, ret->ID);
Link_output(after);
printf("After end.\n\n");
Link_arrange_ID(test);
Link_display(test);
printf("Arrange end.\n\n");
Link_free(test);
}
/**
* 1. Search
* 2. Before
* 3. After
* 4. Arrange
* 5. Copy
* 6. Swap
*/
#endif
#if false
/* test4 */ {
Std* test = Link_created();
Link_display(test);
printf("Display end.\n\n");
Link_delete_ID(&test, 2);
Link_display(test);
printf("Delete_ID end.\n\n");
Link_display_name(test);
char name[21];
scanf("%s", name);
Link_delete_name(&test, name);
Link_display(test);
printf("Delete_name end.\n\n");
Link_delete_gender(&test, 0);
Link_display(test);
printf("Delete_gender end.\n\n");
Link_delete_age(&test, 18);
Link_display(test);
printf("Delete_age end.\n\n");
Link_free(test);
}
/**
* 1. Delete
* 2. Display Name
*/
#endif
#if false
/* test5 */ {
Std* test = NULL;
Link_malloc(&test, 1);
Link_input(test);
printf("----------------\n");
printf("ID: %d\n", Link_get_ID(test));
printf("name: %s\n", Link_get_name(test));
if (Link_get_gender(test) == man) {
printf("gender: man\n");
}
else {
printf("gender: women\n");
}
printf("age: %d\n", Link_get_age(test));
printf("----------------\n");Link_display(test);
printf("Get end.\n\n");
Link_free(test);
}
/**
* 1. Get
*/
#endif
#if false
/* test6 */ {
Std* test = Link_created();
Link_display(test);
printf("Display end.\n\n");
Link_insert_ID_aft(test, 1);
Link_display(test);
printf("Insert_aft end.\n\n");
Link_insert_ID_bef(&test, 1);
Link_display(test);
printf("Insert_bef end.\n\n");
Std* ID_2 = Link_search(test, 2);
Link_insert_Std_aft(test, ID_2);
Link_display(test);
printf("Insert_aft end.\n\n");
Link_insert_Std_bef(&test, ID_2);
Link_display(test);
printf("Insert_bef end.\n\n");
Link_add_head(&test);
Link_display(test);
printf("Add_head end.\n\n");
while (test->next) {
test = test->next;
}
Link_add_end(test);
Link_display(test);
printf("Add_end end.\n\n");
Link_free(test);
}
/**
* 1. Insert
* 2. Add
*/
#endif
#if false
/* test7 */ {
Std* test1 = NULL;
Link_malloc(&test1, 1);
Link_input(test1);
Std* test2 = NULL;
Link_malloc(&test2, 1);
Link_input(test2);
Std* test3 = NULL;
Link_malloc(&test3, 1);
Link_input(test2);
Std* test4 = NULL;
Link_malloc(&test4, 1);
Link_linked(test1, test2);
Link_linked(test2, test3);
Link_copy_all(test4, test2);
Link_linked(test1, test4);
free(test2);
Link_display(test1);
printf("Display end.\n\n");
Link_free(test1);
}
/**
* 1. Linked
* 2. Copy All
*/
#endif
return 0;
}
Link_add.c
#include "head.h"
bool Link_add_head(Std** head)
{
if (*head == NULL) {
return false;
} // 若为空链表则返回
do {
Std *new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新的节点
new->next = *head; // 链接
*head = new; // 改变头指针
} while (Link_input_check()); // 按照输入判断是否继续添加
return true;
}
bool Link_add_end(Std* end)
{
if (end == NULL) {
return false;
} // 若为空链表则返回
do {
Std *new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新的节点
end->next = new; // 链接
end = new; // 改变尾指针
} while (Link_input_check()); // 按照输入判断是否继续添加
return true;
}
Link_after.c
#include "head.h"
Std* Link_after(Std* head, int index_ID)
{
if (head == NULL) {
return NULL;
} // 若为空链表则返回false
while (head != NULL) {
if (head->ID == index_ID) {
return head->next; // 找到则返回该节点
}
head = head->next;
} // 遍历链表
return NULL; // 找不到则返回NULL
}
Link_arrange.c
#include "head.h"
bool Link_arrange_ID(Std* head)
{
if (head == NULL) {
return true;
}
Std* i = head;
while (i->next != NULL) {
Std* j = i;
int min_ID = j->ID;
Std* min = j;
while (j->next != NULL) {
if (j->next->ID < min_ID) {
min_ID = j->next->ID;
min = j->next;
}
j = j->next;
}
Link_swap(i, min);
i = i->next;
} // 选择排序
return true;
}
Link_before.c
#include "head.h"
Std* Link_before(Std* head, int index_ID)
{
if (head == NULL) {
return NULL;
} // 若为空链表则返回false
if (head->ID == index_ID) {
return NULL;
} // 若该节点为头节点则返回NULL
while (head->next != NULL) {
if (head->next->ID == index_ID) {
return head; // 找到则返回该节点
}
head = head->next;
} // 遍历链表
return NULL; // 找不到则返回NULL
}
Link_copy.c
#include "head.h"
bool Link_copy_all(Std* dest, Std* src)
{
if (dest == NULL || src == NULL) {
return false;
}
dest->ID = src->ID;
strcpy(dest->name, src->name);
dest->gender = src->gender;
dest->age = src->age;
dest->next = src->next;
return true;
}
bool Link_copy_value(Std* dest, Std* src)
{
if (dest == NULL || src == NULL) {
return false;
}
dest->ID = src->ID;
strcpy(dest->name, src->name);
dest->gender = src->gender;
dest->age = src->age;
return true;
}
Link_created.c
#include "head.h"
Std* Link_created(void)
{
Std* head = NULL;
Std* p = NULL;
Link_malloc(&p, 1);
Link_input(p); // 先创建头节点
head = p;
while (Link_input_check()) {
Link_malloc(&(p->next), 1);
Link_next(&p);
Link_input(p);
} // 根据输入判断是否继续输入
return head; // 返回头指针
}
Link_delete.c
#include "head.h"
bool Link_delete_ID(Std** head, int index_ID)
{
if (*head == NULL) {
return false;
} // 若为空链表,返回false
Std* det = Link_search(*head, index_ID); // 查找对应节点
if (det == NULL) {
return false;
} // 若找不到,返回false
if ( Link_delete_Std(&(*head), det) ) {
return true;
} // 删除成功返回true
else {
return false;
} // 删除失败返回false
}
bool Link_delete_name(Std** head, char* index_name)
{
if (*head == NULL) {
return false;
} // 若为空链表,返回false
Std* p = *head;
while (p) { // 遍历链表
if (strcmp(p->name, index_name) == 0) {
Link_delete_Std(&(*head), p); // 若相同则删除对应节点
}
p = p->next;
}
return true;
}
bool Link_delete_gender(Std** head, Gender index_gender)
{
if (*head == NULL) {
return false;
} // 若为空链表,返回false
Std* p = *head;
while (p) { // 遍历链表
if (p->gender == index_gender) {
Link_delete_Std(&(*head), p); // 若相同则删除对应节点
}
p = p->next;
}
return true;
}
bool Link_delete_age(Std** head, int index_age)
{
if (*head == NULL) {
return false;
} // 若为空链表,返回false
Std* p = *head;
while (p) { // 遍历链表
if (p->age == index_age) {
Link_delete_Std(&(*head), p); // 若相同则删除对应节点
}
p = p->next;
}
return true;
}
bool Link_delete_Std(Std** head, Std* index_Std)
{
if (*head == NULL) {
return false;
} // 若为空链表,返回false
Std* before = Link_before(*head, index_Std->ID); // 找到链表的前一个节点(前一个节点存在则节点一定存在)
if (before == NULL) { // 前一个节点为空时
if ((*head)->ID == index_Std->ID) { // 判断节点是否为头节点
Std* temp = *head;
*head = (*head)->next;
free(temp);
return true; // 删除头节点
}
else {
return false; // 若不是头节点则返回false(链表中不存在这个节点)
}
}
Std* after = index_Std->next; // 找到链表的后一个节点(此时节点一定存在)
if (after == NULL) { // 后一个节点为空时(即节点为尾节点)
before->next = NULL;
free(index_Std);
return true; // 删除尾节点
}
else {
before->next = after;
free(index_Std);
return true; // 删除中间节点
}
}
Link_display.c
#include "head.h"
bool Link_display(Std* head)
{
if (head == NULL) {
return false;
} // 若为空链表则返回
while ( head != NULL ) {
Link_output(head);
head = head->next;
}
return true;
}
bool Link_display_name(Std* head)
{
if (head == NULL) {
return false;
} // 若为空链表则返回
printf("----------------\n");
while (head != NULL) {
printf("%s\n", head->name);
head = head->next;
}
printf("----------------\n");
return true;
}
Link_free.c
#include "head.h"
bool Link_free(Std* head)
{
if (head == NULL) {
return false;
} // 若为空链表则返回false
Std* temp = NULL; // 用于保存节点
while (head->next) {
temp = head;
head = head->next;
free(temp);
} // 遍历链表
free(head);
return true;
}
Link_get.c
#include "head.h"
int Link_get_ID(Std* index_Std)
{
return index_Std->ID;
}
char* Link_get_name(Std* index_Std)
{
return index_Std->name;
}
Gender Link_get_gender(Std* index_Std)
{
return index_Std->gender;
}
int Link_get_age(Std* index_Std)
{
return index_Std->age;
}
Link_input.c
#include "head.h"
bool Link_input(Std* index_Std)
{
if (index_Std == NULL) {
return false;
}
printf("Waiting for your input.\n");
printf("0 means man and 1 means women.\n");
printf("----------------\n");
printf("ID: ");
scanf("%d", &(index_Std->ID));
printf("name: ");
scanf("%20s", index_Std->name);
printf("gender: ");
int gender;
scanf("%d", &gender);
if (gender) {
index_Std->gender = women;
} else {
index_Std->gender = man;
}
printf("age: ");
scanf("%d", &(index_Std->age));
index_Std->next = NULL;
printf("----------------\n");
return true;
}
bool Link_input_check(void)
{
getchar();// For get the '\n'
printf("Continue to input?\n\"q\" to quit and \"c\" to continue.\n");
char check;
scanf("%c", &check);
return (check == 'q')?false:true;
}
Link_insert.c
#include "head.h"
bool Link_insert_ID_bef(Std** head, int index_ID)
{
if (head == NULL) {
return false;
} // 若为空链表,返回false
Std* before = Link_before(*head, index_ID); // 找到链表的前一个节点(前一个节点存在则节点一定存在)
if (before == NULL) { // 前一个节点为空时
if ((*head)->ID == index_ID) { // 判断节点是否为头节点
Std* new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新的节点
new->next = *head;
*head = new; // 链接
return true;
}
else {
return false;
}
}
else { // 找到了前一个节点
Std* p = before->next; // 后一个节点(即传入的节点)
Std* new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建节点
before->next = new;
new->next = p; // 链接
return true;
}
}
bool Link_insert_ID_aft(Std* head, int index_ID)
{
if (head == NULL) {
return false;
} // 若为空链表,返回false
Std* p = Link_search(head, index_ID); // 查找对应节点
if (p == NULL) {
return false;
} // 若找不到则返回false
Std* after = p->next; // 下一个节点
if (after == NULL) { // 没有下一个节点则节点为尾节点
Std *new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新的节点
p->next = new; // 链接
return true;
}
else { // 有下一个节点则为中间的节点
Std *new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新的节点
p->next = new;
new->next = after; // 链接
return true;
}
}
bool Link_insert_Std_bef(Std** head, Std* index_Std)
{
if (head == NULL || index_Std == NULL) {
return false;
} // 若为空链表或空节点则返回false
Std* before = Link_before(*head, index_Std->ID); // 前一个节点
if (before == NULL) { // 前一节点为空时
if (index_Std->ID == (*head)->ID) { // 判断是否为头节点
Std *new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新的节点
new->next = *head; // 链接
*head = new; // 改变头指针
return true;
}
else {
return false; // 不是头节点则返回false(该节点不存在)
}
}
else { // 前一节点不为空时
Std *new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新的节点
before->next = new;
new->next = index_Std; // 链接
return true;
}
}
bool Link_insert_Std_aft(Std* head, Std* index_Std)
{
if (head == NULL || index_Std == NULL) {
return false;
} // 若为空链表或空节点则返回false
Std* p = Link_search(head, index_Std->ID); // 查找对应节点
if (p == NULL) {
return false;
} // 若找不到则返回false
Std* after = index_Std->next; // 后一个节点
if (after == NULL) { // 若后一个节点为空则为尾节点
Std *new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新节点
index_Std->next = new; // 链接
return true;
}
else { // 若后一个节点不为空则为中间节点
Std *new = NULL;
Link_malloc(&new, 1);
Link_input(new); // 创建新节点
index_Std->next = new;
new->next = after; // 链接
return true;
}
}
Link_linked.c
#include "head.h"
bool Link_linked(Std* head, Std* end)
{
if (head == NULL || end == NULL) {
return false;
}
head->next = end;
return true;
}
Link_malloc.c
#include "head.h"
bool Link_malloc(Std** p, int len)
{
if (p == NULL) {
return false;
}
*p = (Std*)malloc(len * sizeof(Std));
if (*p == NULL) {
return false;
}
else {
return true;
}
}
Link_next.c
#include "head.h"
bool Link_next(Std** index_Std)
{
if (*index_Std == NULL) {
return false;
}
*index_Std = (*index_Std)->next;
return true;
}
Link_output.c
#include "head.h"
bool Link_output(Std* index_Std)
{
if (index_Std == NULL) {
return false;
}
printf("----------------\n");
printf("ID: %d\n", index_Std->ID);
printf("name: %s\n", index_Std->name);
if (index_Std->gender == man) {
printf("gender: man\n");
}
else {
printf("gender: women\n");
}
printf("age: %d\n", index_Std->age);
printf("----------------\n");
return true;
}
Link_reversal.c
#include "head.h"
bool Link_reversal(Std** head)
{
if (*head == NULL|| (*head)->next == NULL) {
return false;
} // 若为空链表或只有一个节点的链表则返回false(不能反转)
Std* p = NULL;
Std* q = NULL;
Std* r = NULL; // 用于反转的指针
p = *head;
q = p->next;
p->next = NULL; // 头变尾
while ( q != NULL ) { // 当到末尾时结束循环
r = q->next;
q->next = p;
p = q;
q = r;
} // 将后一个节点拆下来链接到前一个节点上
*head = p; // 改变头节点
return true;
}
Linkl_search.c
#include "head.h"
Std* Link_search(Std* head, int index_ID)
{
if (head == NULL) {
return NULL;
} // 如果链表为空则返回false
while (head != NULL) { // 遍历链表
if (head->ID == index_ID) {
return head;
} // 若找到则返回节点
head = head->next; // 遍历
}
return NULL; // 遍历结束(找不到)返回false
}
Link_swap.c
#include "head.h"
bool Link_swap(Std* a, Std* b)
{
if (a == NULL || b == NULL) {
return false;
}
Std* temp = NULL; // 创建临时节点
temp = (Std*)malloc(sizeof(Std)); // 分配内存
Link_copy_value(temp, a);
Link_copy_value(a, b);
Link_copy_value(b, temp); // 交换内容
free(temp); // 释放临时节点的内存
return true;
}