厦大2021届大一小学期C语言作业3【链表】

链表

  • 1、输入程序、调试程序,使程序能正确运行。
  • 2、查出并修正程序中的错误。
  • 3、改进、完善程序中你认为写得不好的地方。
  • 4、增加、完善程序功能:
  • ​ 1) 输入数据及统计数据存入磁盘文件中,
  • ​ 2) 平时、总评成绩也统计、算标准差,
  • ​ 3)增加期中成绩,总评成绩保留1位小数…
  • 5、按成绩排序(多关键字)
  • 6、思考: 只有1~2位小数的浮点数的整数算法。

课本6. 进阶—约瑟夫环问题(任关键字k,任总人数n)

共有n个人围成一圈,报到k的人退出游戏。按顺序输出退出游戏的人的原序号,并输出最后留下的人的原序号

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode {
	int number;
	struct LNode *next;
} LNode, *LinkList;
int k, n; //全局变量
LNode *InitList(LinkList &L) { //初始化循环链表
	int i = 0;
	L = (LNode *)malloc(sizeof(LNode)); //创建头结点,头结点不存数据
	if (L == NULL) {
		printf("内存不足,分配失败\n");
		exit(1);
	}
	L->next = NULL;
	LNode *head = L->next, *p1, *p2;//head为头结点指向的下一结点
	while (i != n) {
		p1 = (LNode *)malloc(sizeof(LNode));
		p1->number = ++i;
		if (head == NULL) {
			head = p1;
		} else {
			p2->next = p1;
		}
		p2 = p1;
		if (i == n)
			break;
	}
	p2->next = head;
	return head;
}
void print(LNode *head) {
	LNode *p1 = head, *p2 = p1->next; //分别指向第一第二个结点
	int i = 1;
	while (p2->next != p1) {
		if (i != k - 1) { //p1,p2顺延一位
			p1 = p2;
			p2 = p1->next;
			i++;
		}
		if (i == k - 1) { //删除p2指向结点
			printf("%d ", p2->number);
			p2 = p2->next;
			p1->next = p2;

			p1 = p2;
			p2 = p1->next;
			i = 1;
		}
	}
	if (p2->next == p1) { //剩两个结点
		if (k % 2 == i % 2) { //若k,i同奇同偶
			printf("%d ", p1->number);
			printf("%d ", p2->number);
		} else {
			printf("%d ", p2->number);
			printf("%d ", p1->number);
		}
	}
}
int main() {
	printf("请输入总人数:\n");
	scanf("%d", &n);
	printf("请输入关键数字:\n");
	scanf("%d", &k);
	printf("喊到第%d的人退出报数\n", k);
	LinkList L;//创建头指针
	LNode *head = InitList(L);
	print(head);
	return 0;
}

在这里插入图片描述

课本7.建立链表+输出原链表+删除指定节点+输出新链表

#include<stdio.h>
#include<stdlib.h>
#define LEN sizeof(struct Student)
struct Student {
	long num;
	float score;
	struct Student *next;
};
int n;
struct Student *creat(struct Student *L) {//建立链表,含头结点
	L = (struct Student *)malloc(sizeof(struct Student));
	if (L == NULL) {
		printf("内存不足,分配失败");
		exit(1);
	}

	struct Student *head;//第一个结点
	struct Student *p1, *p2;
	n = 0;
	p1 = p2 = (struct Student *)malloc(LEN);
	scanf("%ld,%f", &p1->num, &p1->score);
	head = NULL;
	while (p1->num != 0) {
		n++;
		if (n == 1) {
			head = p1;
			L->next = head;
		} else
			p2->next = p1;
		p2 = p1;
		p1 = (struct Student *)malloc(LEN);
		scanf("%ld,%f", &p1->num, &p1->score);
	}
	p2->next = NULL;
	return L;
}
void print(struct Student *L) {
	struct Student *p;
	printf("\nNow,These %d records are:\n", n);
	p = L; //使p指向头结点
	if (L != NULL) //若不是空表{
		while (p != NULL) {
			p = p->next;
			printf("%ld,%.f\n", p->num, p->score);
		}
}
bool ListDelete(struct Student* &L, int i) { //删除第i个结点(带头文件)
	if (i < 1)
		return false;
	struct Student *p;
	p = L; //L指向头结点
	int j = 0;
	while (p != NULL && j < i - 1) { //找到第i-1个结点
		p = p->next;
		j++;
	}
	if (p == NULL || p->next == NULL) //i值超过原链表长度 或 第i-1个结点后无其他结点
		return false;
	struct Student *q;
	q = p->next;
	p->next = q->next;
	free(q);
	return true;
}
int main() {
	struct Student *pt;
	pt = creat(pt);
	print(pt);
	ListDelete(pt, 4); //删除第4个结点
	print(pt);
	return 0;
}

课本8.单链表的插入(带头结点)

bool insert(LinkList &L,int i,int e){//在第i个位置插入元素e.用ListInsert做名称更好
  if(i<1);
  return false;
  LNode *p;
  p=L;//L指向头结点,头结点为第0个结点
  int j=0;
  while(p!=NULL&&j<i-1){
    p=p->next;
    j++;
  }
  if(p==NULL)//i的值大于原链表长度
    retrun false;
  LNode *s=(LNode *)malloc(sizeof(LNode));
  s->data=e;
  s->next=p->next;
  p->next=s;
  return true;//插入成功
}

课本9.实现链表的建立,删除,插入,打印

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode {
	int data;
	struct LNode *next;
}*LinkList, LNode;
int n;
LNode *creat(LinkList &L) {//建立链表,含头结点
	L = (LNode *)malloc(sizeof(LNode));
	if (L == NULL) {
		printf("内存不足,分配失败");
		exit(1);
	}

	LNode *head;//第一个结点
	LNode *p1, *p2;
	n = 0;
	p1 = p2 = (LNode *)malloc(sizeof(LNode));
	scanf("%d", &p1->data);
	head = NULL;
	while (p1->data != 0) {
		n++;
		if (n == 1) {
			head = p1;
			L->next = head;
		} else
			p2->next = p1;
		p2 = p1;
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->data);
	}
	p2->next = NULL;
	return L;
}
void print(LinkList L) {
	LNode *p;
	printf("\nNow,These %d records are:\n", n);
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d ", p->data);
			p = p->next;
		}
		putchar('\n');
}
bool ListDelete(LinkList &L, int i) { //删除第i个结点(带头文件)
	if (i < 1)
		return false;
	LNode *p;
	p = L; //L指向头结点
	int j = 0;
	while (p != NULL && j < i - 1) { //找到第i-1个结点
		p = p->next;
		j++;
	}
	if (p == NULL || p->next == NULL) //i值超过原链表长度 或 第i-1个结点后无其他结点
		return false;
	LNode *q;
	q = p->next;
	p->next = q->next;
	free(q);
	n--;
	return true;
}
bool ListInsert(LinkList &L, int i, int e) { //在第i个位置插入元素e.
	if (i < 1)
		return false;
	LNode *p;
	p = L; //L指向头结点,头结点为第0个结点
	int j = 0;
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	if (p == NULL) //i的值大于原链表长度
		return false;
	LNode *s = (LNode *)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	n++;
	return true;//插入成功
}
int main() {
	LinkList pt;
	int i, e;
	pt = creat(pt);
	printf("删除第()个结点: ");
	scanf("%d", &i);
	ListDelete(pt, i); //删除第4个结点
	printf("删除第%d个结点后的链表:\n", i);
	print(pt);
	printf("请输入插入元素: ");
	scanf("%d", &e);
	ListInsert(pt, i, e);
	printf("插入元素%d后的链表:\n", e);
	print(pt);
	return 0;
}

在这里插入图片描述

课本10.拼接a,b链表,并按学号排序

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode {
	int num;
	int score;
	struct LNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));
	if (L == NULL) {
		printf("内存不足,分配失败");
		exit(1);
	}

	LNode *head = NULL; //第一个结点
	LNode *p1, *p2;
	p1 = p2 = (LNode *)malloc(sizeof(LNode));
	scanf("%d%d", &p1->num, &p1->score);
	while (p1->num != 0) {
		if (head == NULL) {
			head = p1;
			L->next = head;
		} else
			p2->next = p1;
		p2 = p1;
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d%d", &p1->num, &p1->score);
	}
	p2->next = NULL;
	return L;
}
LNode* Connect(LinkList &L1, LinkList &L2) {
	LNode *p1 = L1;
	while (p1->next != NULL) { //找到最后一个结点
		p1 = p1->next;
	}
	p1->next = L2->next; //L1的最后一个结点指向L2的第一个结点
	free(L2);//释放L2头结点
	return L1;
}
LinkList BubbleSort(LinkList &L) { //冒泡排序
	LNode *p = L;
	int count = 0;
	while (p->next != NULL) { //计算L的结点数目
		p = p->next;
		count++;
	}
	p = L;
	LNode *q;
	for (int i = 0; i < count - 1; i++) {
		p = p->next;
		q = p;
		for (int j = i + 1; j < count; j++) {
			q = q->next;
			if (q->num < p->num) {
				int t = p->num;
				p->num = q->num;
				q->num = t;

				t = p->score;
				p->score = q->score;
				q->score = t;
			}
		}
	}
	return L;
}
void print(LinkList L) {
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d %d\n", p->num, p->score);
			p = p->next;
		}
	putchar('\n');
}
int main() {
	LinkList a, b;
	printf("请输入链表a的数据:\n");
	a = creat(a);
	printf("请输入链表b的数据:\n");
	b = creat(b);
	LinkList c = Connect(a, b);
	print(c);
	c = BubbleSort(c);
	print(c);
	return 0;
}

在这里插入图片描述

课本11删除a链表中与b链表学号一致的结点

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct LNode {
	int num;
	char name[50] = {0};
	struct LNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d%s", &p1->num,p1->name);
		if(p1->num==0) break;
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;
	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}

void print(LinkList L) {
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d %s\n", p->num, p->name);
			p = p->next;
		}
	putchar('\n');
}
void copy(char x[50], char y[50]) {
	char t;
	for (int i = 0; i < strlen(x) || i < strlen(y); i++) {
		x[i]=y[i];
	}
}
LinkList LNodeDelete(LinkList &X, LinkList &Y) {
	LNode *p=X->next,*q = Y->next;
	while (p!= NULL) {
		q = Y->next;
		int flag=0;
		while (q!= NULL) {
			if(p->num==q->num) {
				flag=1;
				LNode *temp=p->next;
				p->num=temp->num;//等效为p向后移动一位
				copy(p->name,temp->name);
				p->next=temp->next;
				break;
			}
			q = q->next;
		}
		if(flag==1) {//若发生指定结点删除,则p不移动
			p=p;
		} else//若p指向的元素与b链表无重复,指向下一个
			p=p->next;

	}
	return X;
}

int main() {
	LinkList a, b;
	printf("请输入链表a的数据:\n");
	a = creat(a);
	printf("请输入链表b的数据:\n");
	b = creat(b);
	printf("删除a链表中与b链表有相同学号的结点:\n");
	a = LNodeDelete(a, b);
	print(a);
	return 0;
}

在这里插入图片描述

课本12 输入一个年龄,将链表中对应年龄的结点删除

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode {
	int num;
	char name[50] = {0};
	char gender[10] = {0};
	int age;
	struct LNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));
	if (L == NULL) {
		printf("内存不足,分配失败");
		exit(1);
	}

	LNode *head = NULL; //第一个结点
	LNode *p1, *p2;
	p1 = p2 = (LNode *)malloc(sizeof(LNode));
	scanf("%d%s%s%d", &p1->num, p1->name, p1->gender, &p1->age);
	while (p1->num != 0) {
		if (head == NULL) {
			head = p1;
			L->next = head;
		} else
			p2->next = p1;
		p2 = p1;
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d%s%s%d", &p1->num, p1->name, p1->gender, &p1->age);
	}
	p2->next = NULL;
	return L;
}
void LNodeDelete(LinkList L,int Age){
	LNode *p=L,*q;
	while(q->next!=NULL){
		p=p->next;
		q=p->next;
		if(p==L->next&&Age==p->age){
			L->next=p->next;
			free(p);
		}
		else if(Age==q->age){//删除q指向的结点
			p->next=q->next;
			free(q);
		}
	}
}
void print(LinkList L) {
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d %s %s %d\n", p->num, p->name,p->gender,p->age);
			p = p->next;
		}
	putchar('\n');
}
int main(){
	LinkList a;
	a=creat(a);
	print(a);
	int Age;
	while(~scanf("%d",&Age)){
	LNodeDelete(a,Age);
	print(a);
}
}

在这里插入图片描述

链表1.翻转单链表

法一:

核心:用p,q指针实现翻转,temp指针标记q的下一个位置

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int val;
	struct ListNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));
	if (L == NULL) {
		printf("内存不足,分配失败");
		exit(1);
	}
	LNode *head = NULL; //第一个结点
	LNode *p1, *p2;
	p1 = p2 = (LNode *)malloc(sizeof(LNode));
	scanf("%d", &p1->val);
	while (p1->val != 0) {
		if (head == NULL) {
			head = p1;
			L->next = head;
		} else
			p2->next = p1;
		p2 = p1;
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->val);
	}
	p2->next = NULL;
	return L;
}
LinkList ReverseList(LinkList &L){
	LNode *p,*q,*temp;
	p=NULL;q=L->next;temp=q->next;
	while(q!=NULL){
		q->next=p;
		p=q;
		q=temp;
		if(q!=NULL)
		temp=q->next;
	}
	return p;
}
void print(LinkList head) {//不带头结点
	LNode *p;
	p = head; //使p指向第一个结点
	if (head != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d ", p->val);
			p = p->next;
		}
	putchar('\n');
}
int main()
{
	LinkList L;
	L=creat(L);
	L=ReverseList(L);
	print(L);
}

法二:

用头插法实现链表逆置

不断读取L1中的数据,用头插法插入L2头结点之后

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int val;
	struct ListNode* next;
} LNode, *LinkList;
LinkList List_HeadInsert(LinkList &L2,LinkList L1) {
	L2=(LNode *)malloc(sizeof(LNode));
	L2->next=NULL;//初始为空链表
	LNode *p=L1->next;
	LNode *s;
	while(p!=NULL) {
		s=(LNode *)malloc(sizeof(LNode));
		s->val=p->val;
		s->next=L2->next;
		L2->next=s;
		p=p->next;
	}
	return L2;
}
void print(LinkList L) {//带头结点
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L!= NULL) //若不是空表{
		while (p != NULL) {
			printf("%d ", p->val);
			p = p->next;
		}
	putchar('\n');
}
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->val);
		if(p1->val==0) break;
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;

	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}
int main() {
	LinkList L1;
	creat(L1);
	LinkList L2;
	L2=List_HeadInsert(L2,L1);
	print(L2);
}

法三:

用头插法原地逆置

实质:用头插实现逆序存入

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int val;
	struct ListNode* next;
} LNode, *LinkList;
LinkList List_HeadInsert(LinkList &L){
  L=(LNode *)malloc(sizeof(LNode));
  L->next=NULL;//初始为空链表
  int x;
  scanf("%d",&x);
  LNode *s;
  while(x!=0){
    s=(LNode *)malloc(sizeof(LNode));
    s->val=x;
    s->next=L->next;
    L->next=s;
    scanf("%d",&x);
  }
  return L;
}
void print(LinkList L) {//带头结点
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L!= NULL) //若不是空表{
		while (p != NULL) {
			printf("%d ", p->val);
			p = p->next;
		}
	putchar('\n');
}
int main(){
	LinkList L;
	L=List_HeadInsert(L);
	print(L);
}

在这里插入图片描述

链表2 删除单链表中重复元素

重点:末尾的处理

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int val;
	struct ListNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));
	if (L == NULL) {
		printf("内存不足,分配失败");
		exit(1);
	}

	LNode *head = NULL; //第一个结点
	LNode *p1, *p2;
	p1 = p2 = (LNode *)malloc(sizeof(LNode));
	scanf("%d", &p1->val);
	while (p1->val != 0) {
		if (head == NULL) {
			head = p1;
			L->next = head;
		} else
			p2->next = p1;
		p2 = p1;
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->val);
	}
	p2->next = NULL;
	return L;
}
LinkList BubbleSort(LinkList &L) { //冒泡排序
	LNode *p = L;
	int count = 0;
	while (p->next != NULL) { //计算L的结点数目
		p = p->next;
		count++;
	}
	p = L;
	LNode *q;
	for (int i = 0; i < count - 1; i++) {
		p = p->next;
		q = p;
		for (int j = i + 1; j < count; j++) {
			q = q->next;
			if (q->val < p->val) {
				int t = p->val;
				p->val = q->val;
				q->val = t;
			}
		}
	}
	return L;
}
void print(LinkList L) {//带头结点
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d ", p->val);
			p = p->next;
		}
	putchar('\n');
}
LinkList LNodeDelete(LinkList &L) {
	LNode *p = L, *q = L->next;
	while (q != NULL && p != NULL) {

		while(p->val == q->val) { //删除q指向的结点
			p->next = q->next;
			if(p->next==NULL) //若p->next=NULL,最后一次while还会执行判断q->val
			break;
			q=p->next;
		}
		p = p->next;
		if(p!=NULL)
		q = p->next;
	}
	return L;
}
int main() {
	LinkList a;
	a = creat(a);
	a = BubbleSort(a);
	a = LNodeDelete(a);
	print(a);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

链表3 一个排序链表,删除所有含重复数字的结点

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int val;
	struct ListNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->val);
		if(p1->val==0) breaka;
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;
	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}
LinkList BubbleSort(LinkList &L) { //冒泡排序
	LNode *p = L;
	int count = 0;
	while (p->next != NULL) { //计算L的结点数目
		p = p->next;
		count++;
	}
	p = L;
	LNode *q;
	for (int i = 0; i < count - 1; i++) {
		p = p->next;
		q = p;
		for (int j = i + 1; j < count; j++) {
			q = q->next;
			if (q->val < p->val) {
				int t = p->val;
				p->val = q->val;
				q->val = t;
			}
		}
	}
	return L;
}
void print(LinkList L) {//带头结点
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表
		while (p != NULL) {
			printf("%d ", p->val);
			p = p->next;
		}
	putchar('\n');
}
LinkList LNodeDelete(LinkList &L) {
	LNode *p = L->next, *q = p->next;
	while (q != NULL && p != NULL) {
		int flag=0;
		while(p->val == q->val) { //删除q指向的结点
			p->next = q->next;
			if(p->next==NULL) //若p->next=NULL,最后一次while还会执行判断q->val
				break;
			q=p->next;
			flag=1;
		}
		if(flag==1) {
			LNode *temp=p->next;
			p->val=temp->val;
			p->next=temp->next;
			p = p;
		}
		if(flag==0)
			p=p->next;
		if(p!=NULL)
			q = p->next;
	}
	return L;
}
int main() {
	LinkList a;
	a = creat(a);
	a = BubbleSort(a);
	a = LNodeDelete(a);
	print(a);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

链表4 用两个链表分别逆序存储一个非负数字,返回一个新链表来表示他们的和。除0以外,两个数组均不以0开头

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int val;
	struct ListNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->val);
		if(p1->val==0) break;
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;
	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}
LinkList addTwoNumbers(LinkList X,LinkList Y) {
	LNode *p=X->next,*q=Y->next;
	int N;
	while(p!=NULL||q!=NULL) {
		N=p->val+q->val;
		if(N<10)
			p->val=N;
		else {//若需进位
			p->val=N%10;
			if(p->next!=NULL)
				p->next->val++;
			else {
				LNode *temp=(LNode *)malloc(sizeof(LNode));
				temp->val=0;//清空脏数据
				p->next=temp;
				p->next->val++;
				temp->next=NULL;
				break;
			}
		}
		p=p->next;
		q=q->next;
	}
	return X;
}
int count(LinkList L) { //计算结点数目
	LNode *p=L;
	int n=0;
	while(p->next!=NULL) {
		p=p->next;
		n++;
	}
	return n;
}
void print(LinkList head) {//不带头结点
	LNode *p;
	p = head; //使p指向第一个结点
	if (head != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d", p->val);
			p = p->next;
		}
	putchar('\n');
}
LinkList ReverseList(LinkList &L) { //翻转链表
	LNode *p,*q,*temp;
	p=NULL;
	q=L->next;
	temp=q->next;
	while(q!=NULL) {
		q->next=p;
		p=q;
		q=temp;
		if(q!=NULL)
			temp=q->next;
	}
	return p;
}
int main() {
	LinkList a,b;
	a=creat(a);
	b=creat(b);
	LinkList c;
	if(count(a)<=count(b))
		c=addTwoNumbers(a,b);
	else
		c=addTwoNumbers(b,a);
	c=ReverseList(c);
	print(c);
	return 0;
}

不进位:

在这里插入图片描述

进位:

在这里插入图片描述

链表5.将结点编号为奇数的放一起,偶数的放一起

先奇后偶

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int code;
	int num;
	struct ListNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	int i=0;
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		i++;
		scanf("%d", &p1->num);
		if(p1->num==0) break;
		p1->code=i;
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;

	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}
LinkList oddEvenList(LinkList &L){
	LNode *p,*q,*t;
	p=L->next;
	q=t=p->next;
	while(q->next!=NULL&&p->next!=NULL){
		p->next=q->next;
		p=p->next;
		if(p->next==NULL)break;
		q->next=p->next;
		q=q->next;
	}
	q->next=NULL;
	p->next=t;
	return L;
}
void print(LinkList L) {//带头结点
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表
		while (p != NULL) {
			printf("%d ", p->num);
			p = p->next;
		}
	putchar('\n');
}
int main(){
	LinkList L;
	L=creat(L);
	L=oddEvenList(L);
	print(L);
}

在这里插入图片描述
在这里插入图片描述

链表6. 以x为基础分割链表。保证所有小于x的结点排在 大于等于x的结点左边,若链表含x,x不需要被置于左右两部分之间

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int num;
	struct ListNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->num);
		if(p1->num==0) break;
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;

	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}
LinkList partition(LinkList &L,int x){
	LNode *p=L->next,*q=p->next;
	while(p->next!=NULL){//本质:冒泡排序
		q=p->next;
		while(q!=NULL){
			if(q->num<x&&p->num>=x){
				int t=q->num;
				q->num=p->num;
				p->num=t;
			}
			q=q->next;
		}
		p=p->next;
	}
	return L;
}
void print(LinkList L) {//带头结点
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表
		while (p != NULL) {
			printf("%d ", p->num);
			p = p->next;
		}
	putchar('\n');
}
int main(){
	LinkList L;
	int x;
	L=creat(L);
	scanf("%d",&x);
	L=partition(L,x);
	print(L);
	return 0;
}

在这里插入图片描述

链表7.反复删去链表中总和为0的连续结点组成的序列,知道不能删为止

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int code;
	int num;
	struct ListNode* next;
} LNode, *LinkList;
int n=0;//记录结点数目
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->num);
		p1->code=++n;//自动编号
		if(p1->num==0) {
			n--;
			break;
		}
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;

	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}

bool Delete0sum(LinkList &L) {
	while(1) {
		LNode *p=L->next;
		int presum[n+1]= {0};
		int flag=0;
		for(int i=1; i<=n; i++) {
			p->code=i;
			p=p->next;
		}
		p=L->next;
		for(int i=0; i<n; i++) {
			presum[i+1]=presum[i]+p->num;
			p=p->next;
		}
		for(int i=0; i<n; i++) {

			for(int j=i+1; j<n+1; j++) {
				if(presum[i]==presum[j]) {				//删除编号为i+1~j的结点
					p=L;
					if(i!=0) {
						p=L->next;
						while(p->code<i) {//找到编号为i的结点
							p=p->next;
						}
					}
					while(1) { //删除p的下一个结点
						LNode *t=p->next;
						if(t==NULL||t->code==j+1)
							break;
						p->next=t->next;
						free(t);
						n--;
					}
					flag=1;
					return false;
				}
			}
		}
		if(flag==0)
			return true;//不再删除
	}
}
void print(LinkList L) {//带头结点
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表
		while (p != NULL) {
			printf("%d ", p->num);
			p = p->next;
		}
	putchar('\n');
}
int main() {
	LinkList L;
	L=creat(L);
	while(1) {
		if(Delete0sum(L)==true)
			break;
	}
	print(L);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

链表8. 将两升序链表合并为一个新的升序链表并返回

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode {
	int num;
	struct LNode* next;
} LNode, *LinkList;
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->num);
		if(p1->num==0) break;
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;

	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}
LinkList mergeTwoLists(LinkList &L1,LinkList &L2) { //冒泡排序
	LNode *p1 = L1;
	while (p1->next != NULL) { //找到最后一个结点
		p1 = p1->next;
	}
	p1->next = L2->next; //L1的最后一个结点指向L2的第一个结点
	free(L2);//释放L2头结点
	
	LNode *p = L1;
	int count = 0;
	while (p->next != NULL) { //计算L的结点数目
		p = p->next;
		count++;
	}
	p = L1;
	LNode *q;
	for (int i = 0; i < count - 1; i++) {
		p = p->next;
		q = p;
		for (int j = i + 1; j < count; j++) {
			q = q->next;
			if (q->num < p->num) {
				int t = p->num;
				p->num = q->num;
				q->num = t;
			}
		}
	}
	return L1;
}
void print(LinkList L) {
	LNode *p;
	p = L->next; //使p指向第一个结点
	if (L != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d ", p->num);
			p = p->next;
		}
	putchar('\n');
}
int main() {
	LinkList a, b;
	printf("请输入链表a的数据:\n");
	a = creat(a);
	printf("请输入链表b的数据:\n");
	b = creat(b);
	LinkList c = mergeTwoLists(a, b);
	printf("合并后,新的升序链表为:\n");
	print(c);
	return 0;
}

在这里插入图片描述

链表9.判断回文链表

思路:

用ReverseList将L复制到L2链表中,并将L2链表翻转(注意:得到链表无头结点)

后将L与L2对应比对

若完全相同,则为回文链表

#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode {
	int val;
	struct ListNode* next;
} LNode, *LinkList;
void print(LinkList head) {//不带头结点
	LNode *p;
	p = head; //使p指向第一个结点
	if (head != NULL) //若不是空表{
		while (p != NULL) {
			printf("%d ", p->val);
			p = p->next;
		}
	putchar('\n');
}
LNode *creat(LinkList &L) {//建立链表,并完成赋值(含头结点
	L = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *head = NULL,*p1, *p2; //第一个结点
	while (1) {
		p1 = (LNode *)malloc(sizeof(LNode));
		scanf("%d", &p1->val);
		if(p1->val==0) break;
		if (head == NULL) {
			head = p1;
		} else
			p2->next = p1;
		p2 = p1;

	}
	p2->next = NULL;
	free(p1);
	L->next=head;
	return L;
}
LinkList ReverseList(LinkList headL,LinkList &L2) {
	L2 = (LNode *)malloc(sizeof(LNode));//头结点
	LNode *Head = NULL,*p1, *p2,*p3=headL; //第一个结点
	while (p3!=NULL) {//复制L2为L
		p1 = (LNode *)malloc(sizeof(LNode));
		p1->val=p3->val;
		if (Head== NULL) {
			Head= p1;
		} else
			p2->next = p1;
		p2 = p1;
		p3=p3->next;
	}
	p2->next = NULL;
	L2->next=Head;

	LNode *p=NULL,*q=L2->next,*temp=q->next;
	while(q!=NULL) {//反转L2,返回不带头结点的链表
		q->next=p;
		p=q;
		q=temp;
		if(q!=NULL)
			temp=q->next;
	}
	return p;
}
bool isPalindrome(LinkList &headL) {
	LinkList L2;
	L2=ReverseList(headL,L2);
	print(L2);
	LNode *p=headL,*q=L2;
	while(p!=NULL&&q!=NULL) {
		if(p->val!=q->val)
			return false;
		p=p->next;
		q=q->next;
	}
	return true;
}

int main() {
	LinkList L;
	L=creat(L);
	if(isPalindrome(L->next)) {
		printf("true");
	} else
		printf("false");
	return 0;

}

在这里插入图片描述
在这里插入图片描述

案例3

  • 1、应该中午、晚上分别记最多接受订桌数。

  • 2、应该按人名/手机号输入,不能按编号输入,

       编号不要人工输入,应该自动编号;
    
       应记录订桌时间。
    
  • 3、查询功能不要按编号查询,

      应该按人名、手机号码、时间等查询。
    
  • 4、修改功能也不要按编号,要按人名、手机号等,

       要先显示此条信息,再提示是否修改。
    
  • 5、删除前也应显示此条信息,提示是否确定删除。

  • 6、显示应该按日期/中午/晚上等分开列。

  • 7、表格存到文件中,程序启动时先读文件,

      程序结束时保存文件。
    
  • 8、输入应该有错误重输、连续输入等功能。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#define MaxSize 20    //没用到 
typedef struct guest_info {
	char  name[8]= {0};     //姓名
	int     sum;              //人数
	char  time[10]= {0};     //预订时间
	char set_time[30];//订桌时间
	int number;
	struct guest_info *next;
} GuestLink, *Pointer;
void Insert (Pointer &Head );   //插入
void Search( Pointer Head );    //查询
void Update( Pointer Head );   //修改
void Delete( Pointer &Head ); //删除
void Show( Pointer Head );      //显示
int n=0;
int mid=0,dinner=0;
int mid_max=3,dinner_max=4;
int main() {
	Pointer Head=NULL;
	int i;
	do {
		printf("\n");
		printf("1---插入(Insert)\n");
		printf("2---查询(Search)\n");
		printf("3---修改(Update)\n");
		printf("4---删除(Delete)\n");
		printf("5---显示(Show)\n");
		printf("6---退出(Exit)\n");
		scanf("%d", &i);                          //输入功能选择
		switch(i) {
			case 1:
				Insert(Head);
				break;
			case 2:
				Search(Head);
				break;
			case 3:
				Update(Head);
				break;
			case 4:
				Delete(Head);
				break;
			case 5:
				Show(Head);
				break;
			case 6:
				break;
			default:
				printf("错误,重选");
				break;
		}
	} while(i!=6);                                           //6则退出
	return 0;
}
void  Insert(Pointer &Head) {
	char in_name[8]= {0};
	Pointer p,q,r;
	printf("请输入姓名: ");
	scanf("%s", &in_name);
	p=q=Head;
	while(p!=NULL) {                          //查找,q走到最后一个结点,p指向NULL
		if(strcmp(p->name,in_name)==0) {
			printf("已有");    //已有,不输入
			return;
		} else {
			q=p;    //q指向当前,p指向下一个
			p=p->next;
		}
	}
	//插入操作
	r=( Pointer )malloc( sizeof( GuestLink ) );     //申请空间
	r->next=NULL;                                     //设置队尾指针域
	if(r==NULL) {
		printf("分配空间失败");    //应前移
		return;
	}
	printf("请输入人数: ");
	scanf("%d", &r->sum);
	printf("请输入预定时间:");
	scanf("%s",r->time);
	int m=10*(r->time[0]-'0')+r->time[1]-'0' ;
	if(m>=10&&m<=14&&mid>=mid_max) {
		free(r);
		printf("不好意思,中午的桌已订满\n");
		return ;
	}
	if(m>=17&&m<=20&&dinner>=dinner_max) {
		free(r);
		printf("不好意思,晚上的桌已订满\n");
		return ;
	}
	if(q==NULL)                          //空表?
		Head=r;                           //空表则新结点为头结点
	else {
		q->next=r;    //否则接入表尾
	}
	r->number=++n;
	char *x=r->name;
	for(int i=0; i<strlen(in_name); i++) { //将输入的名字付给新插入的结点
		*x=in_name[i];
		x++;
	}

	if(m>=10&&m<=14)
		mid++;
	if(m>=17&&m<=20)
		dinner++;
	time_t t;
	struct tm *area;
	t=time(NULL);
	area=localtime(&t);
	char *s=asctime(area);
	x=r->set_time;
	for(int i=0; i<strlen(s); i++) {
		*x=s[i];
		x++;
	}
	//应该有输入错误处理!
}
void Search(Pointer Head) {
	char in_name[8]= {0};
	Pointer p=Head;
	printf("请输入姓名: ");
	scanf("%s", in_name);                            //输入编号
	while( p!=NULL) {
		if(strcmp(p->name,in_name)==0) {                  //有则显示
			printf("姓名:%-10s", in_name);
			printf("人数:%-10d", p->sum);
			printf("预定的时间是:%-10s", p->time);
			printf("上次订桌的时间是: %-10s ",p->set_time);
			printf("编号为:%-10d\n",p->number);
			break;
		}              //flag可不可省?(可)
		else
			p=p->next;           //不是则指向下一结点
	}
	if(p==NULL)
		printf("没有查询到!");

}
void Update(Pointer Head) {//不修改结点指向,只修改结点内容,Pointer Head==GuestLink *Head,Head为地址
	char in_name[8]= {0};
	int flag=0;
	Pointer p=Head;
	printf("请输入姓名: ");
	scanf("%s",  in_name);                          //输入编号
	while( p!=NULL) {
		if( strcmp(p->name,in_name)==0 ) {               //是则修改
			printf("姓名:%-10s", in_name);//先显示,再提示是否修改
			printf("人数:%-10d", p->sum);
			printf("预定的时间是:%-10s", p->time);
			printf("上次订桌的时间是: %-10s ",p->set_time);
			printf("编号为:%-10d\n",p->number);
			printf("确定要修改请按1\n");
			scanf("%d",&flag);

			if(flag==0)
				break;
			int m=10*(p->time[0]-'0')+p->time[1]-'0' ;
			if(m>=10&&m<=14)
				mid--;
			if(m>=17&&m<=20)
				dinner--;
			char temp[10]= {0};
			printf("请重新输入预定时间:");
			scanf("%s",temp);
			m=10*(temp[0]-'0')+temp[1]-'0';
			if(m>=10&&m<=14&&mid>=mid_max) {
				printf("不好意思,中午的桌已订满,无法更改,如需要取消,请按4\n");
				break;
			} else if(m>=17&&m<=20&&dinner>=dinner_max) {
				printf("不好意思,晚上的桌已订满,无法更改,如需要取消,请按4\n");
				break;
			} else {
				char *j=p->time;
				for(int i=0; i<strlen(temp); i++) {
					*j=temp[i];
					j++;
				}
			}
			printf("请重新输入姓名: ");
			scanf("%s",in_name);
			char *x=p->name;
			for(int i=0; i<strlen(in_name); i++) { //将输入的名字付给新插入的结点
				*x=in_name[i];
				x++;
			}
			printf("请重新输入人数: ");
			scanf("%d", &p->sum);


			if(m>=10&&m<=14)
				mid++;
			if(m>=17&&m<=20)
				dinner++;

			time_t t;
			struct tm *area;
			t=time(NULL);
			area=localtime(&t);
			char *s=asctime(area);
			x=p->set_time;
			for(int i=0; i<strlen(s); i++) { //将输入的名字付给新插入的结点
				*x=s[i];
				x++;
			}
			break;
		}                  //flag可不可省?(可)
		else
			p=p->next;           //不是则指向下一结点
	}
	if(flag==0) {
		printf("取消修改\n");
	}
	if(p==NULL)
		printf("没有找到要修改的记录!\n");

}
void Delete(Pointer &Head) {//改变结点指向(删除操作),需要加&
	int flag=0;
	char dename[10]= {0};
	Pointer p,q;
	printf("请输入要删除的订单的订桌人姓名: ");
	scanf("%s", &dename);
	p=q=Head;
	while( p!=NULL ) {
		if( strcmp(p->name,dename)==0) {
			printf("姓名:%-10s", p->name);//先显示,再提示是否修改
			printf("人数:%-10d", p->sum);
			printf("预定的时间是:%-10s", p->time);
			printf("上次订桌的时间是: %-10s ",p->set_time);
			printf("编号为:%-10d\n",p->number);
			printf("确定要删除请按1\n");
			scanf("%d",&flag);
			if(flag==0)
				break;

			int m=10*(p->time[0]-'0')+p->time[1]-'0' ;
			if(m>=10&&m<=14)
				mid--;
			if(m>=17&&m<=20)
				dinner--;

			if(p==Head) {
				Head=p->next;
				free(p);
			} else              {
				q->next=p->next;
				free(p);
			}
			break;
		}          //flag可不可省?
		else  {
			q=p;    //q指向当前,p指向下一结点
			p=p->next;
		}
	}
	if(flag==0)
		printf("取消删除\n");
	if(p==NULL)
		printf("没有找到可以删除的数据!\n");      //这样用就对了

}
void Show(Pointer Head) {
	Pointer p=Head;
	printf("中午订桌表\n");
	printf("编号   姓名       人数    时间       订桌时间\n"); //列表显示
	while( p!=NULL ) {
		int m=10*(p->time[0]-'0')+p->time[1]-'0' ;
		if(m>=10&&m<=14) {
			printf("%-10d", p->number);
			printf("%-12s", p->name);
			printf("%-10d", p->sum);
			printf("%-12s", p->time);
			printf("%-10s\n",p->set_time);
		}
		p=p->next;                //指向下一结点
	}
	p=Head;
	printf("晚上订桌表\n");
	printf("编号   姓名       人数    时间       订桌时间\n"); //列表显示
	while( p!=NULL ) {
		int m=10*(p->time[0]-'0')+p->time[1]-'0' ;
		if(m>=17&&m<=20) {
			printf("%-10d", p->number);
			printf("%-12s", p->name);
			printf("%-10d", p->sum);
			printf("%-12s", p->time);
			printf("%-10s\n",p->set_time);
		}
		p=p->next;                //指向下一结点
	}
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快苏排序OAO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值