单链表
本周主要想学习一下链表的基础知识,首先见识到的就是单链表,而实现的第一种方法就是头插法,关于头插法的一些理解,已经写到了注释里面
#include<stdio.h>
#include<stdlib.h>
void getInput(struct Book* book);
void addBook(struct Book** library);
void printLibrary(struct Book* library);
void releaseLibrary(struct Book** library);
struct Book {
char title[128];
char author[40];//前两行为信息域
struct Book* next;//指针域,指向下一个信息域,直到指向NULL,显然,我们需要一个
//头指针,指向第一个指针域,同样,我们的头插法便是对这个头指针进行操作,
//改变我们头指针指向的值,最终在链表中插入一个新元素
};
void getInput(struct Book* book) {
printf("请输入书名:");
scanf_s("%s", book->title, 128);
printf("请输入作者:");
scanf_s("%s", book->author, 40);
}
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;//temp存储的就是头指针指向的这个信息域的地址
*library = book;//把book即新增加的这个节点的信息域赋给library也就是我们的头指针
book->next = temp;//这个时候把指针域指向原来的第一个节点,完成增加元素的目的
//所以,这种增加元素的方式是将新增的元素排列到最顶端的,故称为头插法,
//当然,还有尾插法的啦
}
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:\n", 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;
}
当然咯,还有尾插法的呀!头插法与尾插法只有一点点思路上的不同,只需要将addLibrary函数做一点改动即可,代码如下:
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==NULL;
//插入数据;;;
temp->next = book;//将新值插入进去
book->next = NULL;//下一个值改为NULL;
}
else {
*library = book;
book->next = NULL;
}
}
这个时候就出现了一个问题,我们在使用尾插法的时候,每次都要将整个链表遍历一遍,效率不高,我们可以直接使用一个指针指向链表的尾部,提高效率,这里只展示与尾插法不同的addBook部分。
void addBook(struct Book** library) {
struct Book* book;
static struct Book* end;//静态存储变量
book = (struct Book*)malloc(sizeof(struct Book));
if (book == NULL) {
printf("内存分配失败!\n");
return;
}
else {
getInput(book);
if (*library == NULL) {
*library = book;
book->next = NULL;
}
else {
end->next = book;
book->next = NULL;
}
end = book;
}
}
还进行了一个小练习,对一个链表实现增删查改,我写了一个比较具体的程序来反映这几个功能,代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Book {
char title[120];
char author[40];
struct Book* next;
};//创建了一个链表
void addBook(struct Book** head);//增加
void deleteBook(struct Book** head);//删除
void searchBook(struct Book *head);//寻找
void changeBook(struct Book *head);//改动
void addInput(struct Book* book);
void printBook(struct Book* head);
void addInput(struct Book* book) {
printf("请输入书名:");
scanf_s("%s", book->title, 120);
printf("请输入作者:");
scanf_s("%s", book->author, 40);
}
void addBook(struct Book** head) {
struct Book* book;
book = (struct Book*)malloc(sizeof(struct Book));
if (book == NULL) {
printf("可用空间不足!\n");
return;
}
else {
printf("请输入你要新增的书:\n");
addInput(book);
if ((*head) != NULL) {
struct Book* temp;
temp = *head;
*head = book;
book->next = temp;
}
else {
*head = book;
book->next = NULL;
}
}
}
void printBook(struct Book* head) {
int cnt = 1;
while (head != NULL) {
printf("Book%d:", cnt++);
printf("书名:%s\n ", head->title);
printf("作者:%s\n ", head->author);
head = head->next;
}
printf("\n");
}
void searchBook(struct Book* head) {
printf("请输入您要查找的书的书名或作者:");
char search[120];
scanf_s("%s", search, 120);
while (head != NULL) {
if ((strcmp(search,head->author)) == 0 ||(strcmp(search,head->title)) == 0) {
printf("您要找的图书找到了!\n");
printf("书名:%s\n", head->title);
printf("作者:%s\n", head->author);
}
head = head->next;
}
}
void deleteBook(struct Book** head) {
printf("请输入你要删除的书的名字:");
char title[120];
struct Book* pf = *head;
struct Book* pb = *head;
scanf_s("%s", title, 120);
while (strcmp(title, pb->title) != 0) {
pf = pb;
pb = pb->next;
}
if (pb != NULL) {
if (pb == *head) {
*head = (*head)->next;
}
else {
pf->next = pb->next;
}
}
}
void changeBook(struct Book* head) {
printf("请输入你要改动第几本书:");
int number;
scanf_s("%d", &number);
for (int i = 0; i < number - 1; i++) {
head = head->next;
}
printf("请输入改动后的书名:");
scanf_s("%s", head->title, 120);
printf("请输入改动后的作者:");
scanf_s("%s", head->author, 40);
}
int main(void) {
struct Book* head = NULL;
while (1) {
printf("请选择你要进行的操作:\n");
printf("**********************\n");
printf("**********************\n");
printf("**1.add 2.delete**\n");
printf("**3.search 4.change**\n");
printf("** 5.exit **\n");
printf("**********************\n");
printf("**********************\n");
int a;
scanf_s("%d", &a);
switch (a) {
case 1:addBook(&head);
printBook(head); break;
case 2:deleteBook(&head);
printBook(head); break;
case 3:searchBook(head); break;
case 4:changeBook(head);
printBook(head); break;
case 5:return 0;
default:printf("请按所给提示输入!\n"); break;
}
}
}
本周还针对字符串做了一些练习,挑选了一个我认为是其中最有难度的题拿出来:
Q1:给定程序的功能主要是将未在字符串S中出现,而在字符串T中出现的字符,形成一个新的字符串放在U中,U按照原字符串中的字符顺序排列,但去掉重复字符
eg:S="12345",T="24667",U=“67”,我的代码如下:
#include<stdio.h>
int main(void) {
char str1[50];
char str2[50];
//目的是将str2内的str1中没有的元素赋给str3,并且不能重复
char str3[50];
int cnt = 0, cnt1 = 0, temp1 = 0;
for (int i = 0; i < 50; i++) {
scanf_s("%c", &str1[i]);
if (str1[i] == '\n') {
break;
}
++cnt;//str1中元素的个数
}
for (int i = 0; i < 50; i++) {
scanf_s("%c", &str2[i]);
if (str2[i] == '\n') {
break;//str2中元素的个数
}
++cnt1;
}
for (int i = 0; i < cnt1; i++) {
int temp = 1;
for (int j = 0; j < cnt; j++) {
if (str2[i] == str1[j]) {
temp = 0;
}
}
if (temp == 1) {
int temp3 = 1;
for (int j = 0; j < temp1; j++) {
if (str3[j] == str2[i]) {
temp3 = 0;
break;
}
}
if (temp3 == 1) {
str3[temp1] = str2[i];
++temp1;
}
}
}
for (int i = 0; i < temp1; i++) {
printf("%c", str3[i]);
}
}
这些就是本周大致的学习内容!