文章目录
- 链表
- 课本6. 进阶---约瑟夫环问题(任关键字k,任总人数n)
- 课本7.建立链表+输出原链表+删除指定节点+输出新链表
- 课本8.单链表的插入(带头结点)
- 课本9.实现链表的建立,删除,插入,打印
- 课本10.拼接a,b链表,并按学号排序
- 课本11删除a链表中与b链表学号一致的结点
- 课本12 输入一个年龄,将链表中对应年龄的结点删除
- 链表1.翻转单链表
- 链表2 删除单链表中重复元素
- 链表3 一个排序链表,删除所有含重复数字的结点
- 链表4 用两个链表分别逆序存储一个非负数字,返回一个新链表来表示他们的和。除0以外,两个数组均不以0开头
- 链表5.将结点编号为奇数的放一起,偶数的放一起
- 链表6. 以x为基础分割链表。保证所有小于x的结点排在 大于等于x的结点左边,若链表含x,x不需要被置于左右两部分之间
- 链表7.反复删去链表中总和为0的连续结点组成的序列,知道不能删为止
- 链表8. 将两升序链表合并为一个新的升序链表并返回
- 链表9.判断回文链表
- 案例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; //指向下一结点
}
}