C语言——单链表、内存池、typedef

目录

一、单链表

1.单链表的声明

2.在单链表中插入元素(头插法)

3.在单链表中插入元素(尾插法)

4.搜索单链表

5.插入元素到指定位置

6.删除指定元素

 二、内存池

通讯录管理程序(添加内存池)代码

 三、typedef

1.C语法和Fortran语法比较

 2.在编程中使用typedef目的


一、单链表

        链表是一种常见的基础数据结构。根据需求,我们可以构造出单链表、双链表、循环链表和块状链表等。链表的出现很大程度上弥补了数组的先天不足。

1.单链表的声明

2.在单链表中插入元素(头插法)

 代码举例:

#include <stdio.h>
#include <stdlib.h>

struct Book
{
	char title[128];
	char author[40];
	struct Book *next;
};

void getInput(struct Book *book);
void addBook(struct Book **library);
void printLibrary(struct Book *library);
void releaseLibrary(struct Book **library);

void getInput(struct Book *book)
{
	printf("请输入书名:");
	scanf("%s",book->title);
	printf("请输入作者:");
	scanf("%s",book->author);
}

void addBook(struct Book **library)
{
	struct Book *book, *temp;
	
	book = (struct Book *)malloc(sizeof(struct Book));
	if(book == NULL)
	{
		printf("内存分配失败了!\n");
		exit(1);
	}
	
	getInput(book);
	
	if (*library != NULL)
	{
		temp = *library;
		*library = book;
		book->next = NULL;
	}
	else
	{
		*library = book;
		book->next = NULL;
	}
}

void printLibrary(struct Book *library)
{
	struct Book *book;
	int count = 1;
	
	book = library;
	while(book != NULL)
	{
		printf("Book%d:",count);
		printf("书名:%s:",book->title);
		printf("作者:%s:",book->author);
		book = book->next;
		count++;
	}
}

void releaseLibrary(struct Book **library)
{
	struct Book *temp;
	
	while(*library != NULL)
	{
		temp = *library;
		*library = (*library)->next;
		free(temp);
	}
}

int main(void)
{
	struct Book *library = NULL;
	int ch;
	
	while(1)
	{
		printf("请问是否需要录入信息(Y/N):");
		do
		{
			ch = getchar();
		}while(ch != 'Y' && ch != 'N');
		
		if(ch == 'Y')
		{
			addBook(&library);
		}
		else
		{
			break;
		}
	}
	
	printf("请问是否需要打印图书信息(Y/N):");
	do
	{
		ch = getchar();
	}while(ch != 'Y' && ch != 'N');
		
	if(ch == 'Y')
	{
		printLibrary(library);
	}
		
	releaseLibrary(&library);
	
	return 0;
}

3.在单链表中插入元素(尾插法)

 代码举例:

#include <stdio.h>
#include <stdlib.h>

struct Book
{
	char title[128];
	char author[40];
	struct Book *next;
};

void getInput(struct Book *book);
void addBook(struct Book **library);
void printLibrary(struct Book *library);
void releaseLibrary(struct Book **library);

void getInput(struct Book *book)
{
	printf("请输入书名:");
	scanf("%s",book->title);
	printf("请输入作者:");
	scanf("%s",book->author);
}

void addBook(struct Book **library)
{
	struct Book *book, *temp;
	
	book = (struct Book *)malloc(sizeof(struct Book));
	if(book == NULL)
	{
		printf("内存分配失败了!\n");
		exit(1);
	}
	
	getInput(book);
	
	if (*library != NULL)
	{
		temp = *library;
		//定位单链表的尾部位置 
		while(temp->next != NULL)
		{
			temp = temp->next;
		}
		//插入数据
		temp->next = book;
		book->next = NULL;
	}
	else
	{
		*library = book;
		book->next = NULL;
	}
}

void printLibrary(struct Book *library)
{
	struct Book *book;
	int count = 1;
	
	book = library;
	while(book != NULL)
	{
		printf("Book%d:",count);
		printf("书名:%s",book->title);
		printf("作者:%s",book->author);
		book = book->next;
		count++;
	}
}

void releaseLibrary(struct Book **library)
{
	struct Book *temp;
	
	while(*library != NULL)
	{
		temp = *library;
		*library = (*library)->next;
		free(temp);
	}
}

int main(void)
{
	struct Book *library = NULL;
	int ch;
	
	while(1)
	{
		printf("请问是否需要录入信息(Y/N):");
		do
		{
			ch = getchar();
		}while(ch != 'Y' && ch != 'N');
		
		if(ch == 'Y')
		{
			addBook(&library);
		}
		else
		{
			break;
		}
	}
	
	printf("请问是否需要打印图书信息(Y/N):");
	do
	{
		ch = getchar();
	}while(ch != 'Y' && ch != 'N');
		
	if(ch == 'Y')
	{
		printLibrary(library);
	}
		
	releaseLibrary(&library);
	
	return 0;
}

运行结果:

 为提高代码运行效率,部分修改如下:

void addBook(struct Book **library)
{
	struct Book *book;
	static struct Book *tail;
	
	book = (struct Book *)malloc(sizeof(struct Book));
	if(book == NULL)
	{
		printf("内存分配失败了!\n");
		exit(1);
	}
	
	getInput(book);
	
	if (*library != NULL)
	{
		tail->next = book;
		book->next = NULL;
	}
	else
	{
		*library = book;
		book->next = NULL;
	}
	tail = book;
}

4.搜索单链表

代码举例:

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

struct Book
{
	char title[128];
	char author[40];
	struct Book *next;
};

void getInput(struct Book *book);
void addBook(struct Book **library);
void printLibrary(struct Book *library);
struct Book *searchBook(struct Book *library ,char *target);
void printBook(struct Book *book);
void releaseLibrary(struct Book **library);

void getInput(struct Book *book)
{
	printf("请输入书名:");
	scanf("%s",book->title);
	printf("请输入作者:");
	scanf("%s",book->author);
}

void addBook(struct Book **library)
{
	struct Book *book;
	static struct Book *tail;
	
	book = (struct Book *)malloc(sizeof(struct Book));
	if(book == NULL)
	{
		printf("内存分配失败了!\n");
		exit(1);
	}
	
	getInput(book);
	
	if (*library != NULL)
	{
		tail->next = book;
		book->next = NULL;
	}
	else
	{
		*library = book;
		book->next = NULL;
	}
	tail = book;
}

void printLibrary(struct Book *library)
{
	struct Book *book;
	int count = 1;
	
	book = library;
	while(book != NULL)
	{
		printf("\nBook%d:",count);
		printf("\n书名:%s",book->title);
		printf("\n作者:%s",book->author);
		book = book->next;
		count++;
	}
}

struct Book *searchBook(struct Book *library ,char *target)
{
	struct Book *book;
	
	book = library;
	while(book != NULL)
	{
		if(strcmp(book->title,target) || !strcmp(book->author,target))
		{
			break;
		}
		book = book->next;
	}
	return book;
}

void printBook(struct Book *book)
{
	printf("书名:%s",book->title);
	printf("作者:%s",book->author);
}

void releaseLibrary(struct Book **library)
{
	struct Book *temp;
	
	while(*library != NULL)
	{
		temp = *library;
		*library = (*library)->next;
		free(temp);
	}
}

int main(void)
{
	struct Book *library = NULL;
	struct Book *book;
	char input[128];
	int ch;
	
	while(1)
	{
		printf("请问是否需要录入信息(Y/N):");
		do
		{
			ch = getchar();
		}while(ch != 'Y' && ch != 'N');
		
		if(ch == 'Y')
		{
			addBook(&library);
		}
		else
		{
			break;
		}
	}
	
	printf("请问是否需要打印图书信息(Y/N):");
	do
	{
		ch = getchar();
	}while(ch != 'Y' && ch != 'N');
		
	if(ch == 'Y')
	{
		printLibrary(library);
	}
	
	printf("\n请输入书名或作者:");
	scanf("%s",input);
	
	book = searchBook(library,input);
	if(book == NULL)
	{
		printf("查找失败!");
	}
	else
	{
		do
		{
			printf("已找到符合条件的图书…\n");
			printBook(book);
		}while((book = searchBook(book->next,input)) != NULL);
	}
	releaseLibrary(&library);
	
	return 0;
}

运行结果(此处有点小问题,欢迎大佬们指正,感谢!):

5.插入元素到指定位置

代码举例:

#include <stdio.h>
#include <stdlib.h>

struct Node
{
	int value;
	struct Node *next;
};

void insertNode(struct Node **head,int value)
{
	struct Node *previous;
	struct Node *current;
	struct Node *new;
	
	current = *head;
	previous = NULL;
	
	while(current != NULL && current->value < value)
	{
		previous = current;
		current = current->next;
	}
	
	new = (struct Node *)malloc(sizeof(struct Node));
	if(new == NULL)
	{
		printf("内存分配失败!\n");
		exit(1);
	}
	
	new->value = value;
	new->next = current;
	
	if(previous == NULL)
	{
		*head = new;
	}
	else
	{
		previous->next = new;
	}
}

void printNode(struct Node *head)
{
	struct Node *current;
	
	current = head;
	while(current != NULL)
	{
		printf("%d ",current->value);
		current = current->next;
	}
	putchar('\n');
}

int main(void)
{
	struct Node *head = NULL;
	int input;
	
	while(1)
	{
		printf("请输入一个整数(输入-1表示结束):");
		scanf("%d",&input);
		if(input == -1)
		{
			break;
		}
		insertNode(&head,input);
		printNode(head);
	}
}

运行结果:

6.删除指定元素

代码如下:

#include <stdio.h>
#include <stdlib.h>

struct Node
{
	int value;
	struct Node *next;
};

void insertNode(struct Node **head,int value)
{
	struct Node *previous;
	struct Node *current;
	struct Node *new;
	
	current = *head;
	previous = NULL;
	
	while(current != NULL && current->value < value)
	{
		previous = current;
		current = current->next;
	}
	
	new = (struct Node *)malloc(sizeof(struct Node));
	if(new == NULL)
	{
		printf("内存分配失败!\n");
		exit(1);
	}
	
	new->value = value;
	new->next = current;
	
	if(previous == NULL)
	{
		*head = new;
	}
	else
	{
		previous->next = new;
	}
}

void printNode(struct Node *head)
{
	struct Node *current;
	
	current = head;
	while(current != NULL)
	{
		printf("%d ",current->value);
		current = current->next;
	}
	putchar('\n');
}

void deleteNode(struct Node **head,int value)
{
	struct Node *previous;
	struct Node *current;
	
	current = *head;
	previous = NULL;
	
	while(current != NULL && current->value != value)
	{
		previous = current;
		current = current->next;
	}
	if(current == NULL)
	{
		printf("找不到匹配的节点!\n");
		return;
	}
	else
	{
		if(previous == NULL)
		{
			*head = current->next;
		}
		else
		{
			previous->next = current->next;
		}
		
		free(current);
	}
}

int main(void)
{
	struct Node *head = NULL;
	int input;
	
	printf("开始测试插入整数…");
	while(1)
	{
		printf("请输入一个整数(输入-1表示结束):");
		scanf("%d",&input);
		if(input == -1)
		{
			break;
		}
		insertNode(&head,input);
		printNode(head);
	}
	
	printf("开始测试删除整数…");
	while(1)
	{
		printf("请输入一个整数(输入-1表示结束):");
		scanf("%d",&input);
		if(input == -1)
		{
			break;
		}
		deleteNode(&head,input);
		printNode(head);
	}
	
}

运行结果:

 二、内存池

其实就是让程序额外维护一个缓存区域

  • 使用单链表来维护一个简单地内存池。
  • 只需要将没有用的内存空间地址依次用一个单链表记录下来;当再次需要的时候,从这个单链表中获取即可。

通讯录管理程序(添加内存池)代码

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

#define MAX 1024

struct Person
{
	char name[40];
	char phone[20];
	struct Person *next;	
};

struct Person *pool = NULL;
int count;
 
void getInput(struct Person *person);
void printPerson(struct Person *person);
void addPerson(struct Person **contacts);
void changePerson(struct Person *contacts);
void delPerson(struct Person **contacts);
struct Person *findPerson(struct Person *contacts);
void displayContacts(struct Person *contacts);
void releaseContacts(struct Person **contacts);
void releasePool(void);
 
void getInput(struct Person *person)
{
	printf("请输入姓名:");
	scanf("%s", person->name);
	printf("请输入电话:");
	scanf("%s", person->phone);
}
 
void addPerson(struct Person **contacts)
{
	struct Person *person;
	struct Person *temp;
	
	//如果内存池非空,则直接从里面获取空间
	if(pool != NULL)
	{
		person = pool;
		pool = pool->next;
		count--;
	}
	
	//如果内存池为空,则调用malloc函数申请新的内存空间
	else
	{
		person = (struct Person *)malloc(sizeof(struct Person));
		if (person == NULL)
		{
			printf("内存分配失败!\n");
			exit(1);
		}
	
	}
	
	
	getInput(person);
	
	// 将person用头插法添加到通讯录
	if (*contacts != NULL)
	{
		temp = *contacts;
		*contacts = person;
		person->next = temp;
	}
	else
	{
		*contacts = person;
		person->next = NULL;
	}
}
 
void printPerson(struct Person *person)
{
	printf("联系人:%s\n", person->name);
	printf("电话:%s\n", person->phone);
}
 
struct Person *findPerson(struct Person *contacts)
{
	struct Person *current;
	char input[40];
	
	printf("请输入联系人:");
	scanf("%s", input);
	
	
	current = contacts;
	while (current != NULL && strcmp(current->name, input))
	{
		current = current->next;
	}
	
	return current;
}
 
void changePerson(struct Person *contacts)
{
	struct Person *person;
	
	person = findPerson(contacts);
	if (person == NULL)
	{
		printf("找不到该联系人!\n");
	}
	else
	{
		printf("请输入新的联系电话:");
		scanf("%s", person->phone);
	}
}
 
void delPerson(struct Person **contacts)
{
	struct Person *temp;
	struct Person *person;
	struct Person *current;
	struct Person *previous;
	
	//先找到待删除的节点指针
	person = findPerson(*contacts);
	if (person == NULL)
	{
		printf("找不到该联系人!\n");
	} 
	else
	{
		current = *contacts;
		previous = NULL;
		
		//current定位到待删除的节点
		while(current != NULL && current != person)
		{
			previous = current;
			current = current->next;
		}
		
		if (previous == NULL)
		{
			//待删除的节点是第一个节点
			*contacts = current->next;
		}
		else
		{
			//待删除的节点不是第一个节点
			previous->next = current->next; 
		}
		
		//判断内存池是不是有空位
		if(count < MAX)
		{
			if(pool != NULL)
			{
				temp = pool;
				pool = person;
				person->next = temp;
			}
			else
			{
				pool = person;
				person->next = NULL;
			}
			count++;
		}
		else
		{
			free(person);
		} 
		 
	}
}
 
void displayContacts(struct Person *contacts)
{
	struct Person *current;
	
	current = contacts;
	while (current != NULL)
	{
		printPerson(current);
		current = current->next;
	}
}
 
void releaseContacts(struct Person **contacts)
{
	struct Person *temp;
	
	while (*contacts != NULL)
	{
		temp = *contacts;
		*contacts = (*contacts)->next;
		free(temp);
	}
}

void releasePool(void)
{
	struct Person *temp;
	
	while(pool != NULL)
	{
		temp = pool;
		pool = pool->next;
		free(temp);
	}
}

int main(void)
{
	int code;
	struct Person *contacts = NULL;
	struct Person *person;
	
	printf("| 欢迎使用通讯录管理程序 |\n");
	printf("|--- 1:插入新的联系人 ---|\n");
	printf("|--- 2:查找新的联系人 ---|\n");
	printf("|--- 3:更改新的联系人 ---|\n");
	printf("|--- 4:删除新的联系人 ---|\n");
	printf("|--- 5:显示新的联系人 ---|\n");
	printf("|--- 6:退出通讯录程序 ---|\n");
	while (1)
	{
		printf("\n请输入指令代码:");
		scanf("%d", &code);
		switch (code)
		{
			case 1: addPerson(&contacts); break;
			
			case 2: person = findPerson(contacts);
					if (person == NULL)
					{
						printf("找不到该联系人!\n");
					}
					else
					{
						printPerson(person);
					}
					break;
			
			case 3: changePerson(contacts); break;
			
			case 4: delPerson(&contacts); break;
			
			case 5: displayContacts(contacts); break;
			
			case 6: goto END;
		}
	}
 
END:
	releaseContacts(&contacts);
	
	releasePool();
	return 0;
}

运行结果:

 三、typedef

typedef是C语言最重要的关键字之一,相比起宏定义的直接替换,typedef是对类型的封装。

1.C语法和Fortran语法比较

C语言定义变量的语法:

  • int a,b,c;
  • float i,j,k;

Fortran语言定义变量的语法:

  • integer :: a,b,c
  • real :: i,j,k

如果能让C语言相同的关键字定义变量:

  • integer a,b,c;
  • real i,j,k;

代码举例1:

#include <stdio.h>

typedef int integer;

int main(void)
{
	integer a;
	int b;
	
	a = 520;
	b = a;
	
	printf("a = %d\n",a);
	printf("b = %d\n",b);
	printf("size of a = %d\n",sizeof(a));
	
	return 0;
	
}

运行结果:

代码举例2:

#include <stdio.h>
#include <stdlib.h>

typedef struct Date
{
	int year;
	int month;
	int day;
}DATE,*PDATE;

int main(void)
{
	struct Date *date;
	date = (PDATE)malloc(sizeof(DATE));
	if(date == NULL)
	{
		printf("内存分配失败!\n");
		exit(1);
	}
	
	date->year = 2022;
	date->month = 8;
	date->day = 19;
	
	printf("%d-%d-%d\n",date->year,date->month,date->day);
	
	return 0;
	
}

运行结果:

 2.在编程中使用typedef目的

  • 一个是给变量起一个容易记住且意义明确的别名;
  • 另一个是简化一些比较复杂的类型声明。

代码举例:

#include <stdio.h>

typedef int (*PTR_TO_ARRAY)[3];

int main(void)
{
	int array[3] = {1, 2, 3};
	PTR_TO_ARRAY ptr_to_array = &array;
	
	int i;
	for(i = 0;i < 3;i++)
	{
		printf("%d\n",(*ptr_to_array)[i]);
	}
	
	return 0;
	
}

运行结果:

 

代码举例:

#include <stdio.h>

typedef int (*PTR_TO_FUN)(void);

int fun(void)
{
	return 520;
}

int main(void)
{
	PTR_TO_FUN ptr_to_fun = &fun;
	
	printf("%d\n",(*ptr_to_fun)());
	
	return 0;
	
}

运行结果:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值