本题要求实现一个将输入的学生成绩组织成单向链表的简单函数。
void input();
该函数利用scanf
从输入中获取学生的信息,并将其组织成单向链表。链表节点结构定义如下:
struct stud_node {
int num; /*学号*/
char name[20]; /*姓名*/
int score; /*成绩*/
struct stud_node *next; /*指向下个结点的指针*/
};
单向链表的头尾指针保存在全局变量head
和tail
中。
输入为若干个学生的信息(学号、姓名、成绩),当输入学号为0时结束。
#include
#include
#include
struct stud_node {
int num;
char name[20];
int score;
struct stud_node *next;
};
struct stud_node *head, *tail;
void input();
int main()
{
struct stud_node *p;
head = tail = NULL;
input();
for ( p = head; p != NULL; p = p->next )
printf("%d %s %d\n", p->num, p->name, p->score);
return 0;
}
/* 你的代码将被嵌在这里 */
1 zhang 78
2 wang 80
3 li 75
4 zhao 85
0
1 zhang 78
2 wang 80
3 li 75
4 zhao 85
void input()
{
//已存在head,tail;
int num;
char name[20];
int score;
struct stud_node *p;
//输入学号姓名班级
scanf("%d",&num);
//学号不为0时循环
while(num!=0)
{
scanf("%s%d",name,&score);
//申请新结点
p = (struct stud_node*)malloc(sizeof(struct stud_node));
p->next=NULL; //新结点的下一个结点指空
//赋值新结点
p->num=num;
strcpy(p->name,name);
p->score=score;
//判断是否为首结点,是则直接赋值,不是则尾接
if(tail==NULL)
head=p;
else
{
tail->next=p;
}
tail=p; //尾指针移动
scanf("%d",&num);
}
}
本题要求实现两个函数,一个将输入的学生成绩组织成单向链表;另一个将成绩低于某分数线的学生结点从链表中删除。
struct stud_node *createlist();
struct stud_node *deletelist( struct stud_node *head, int min_score );
函数createlist
利用scanf
从输入中获取学生的信息,将其组织成单向链表,并返回链表头指针。链表节点结构定义如下:
struct stud_node {
int num; /*学号*/
char name[20]; /*姓名*/
int score; /*成绩*/
struct stud_node *next; /*指向下个结点的指针*/
};
输入为若干个学生的信息(学号、姓名、成绩),当输入学号为0时结束。
函数deletelist
从以head
为头指针的链表中删除成绩低于min_score
的学生,并返回结果链表的头指针。
#include
#include
struct stud_node {
int num;
char name[20];
int score;
struct stud_node *next;
};
struct stud_node *createlist();
struct stud_node *deletelist( struct stud_node *head, int min_score );
int main()
{
int min_score;
struct stud_node *p, *head = NULL;
head = createlist();
scanf("%d", &min_score);
head = deletelist(head, min_score);
for ( p = head; p != NULL; p = p->next )
printf("%d %s %d\n", p->num, p->name, p->score);
return 0;
}
/* 你的代码将被嵌在这里 */
1 zhang 78
2 wang 80
3 li 75
4 zhao 85
0
80
2 wang 80
4 zhao 85
struct stud_node *createlist()
{
//已存在head,tail;
int num;
char name[20];
int score;
struct stud_node *p,*head=NULL,*tail;
tail=head;
//输入学号
scanf("%d",&num);
//学号不为0时循环
while(num!=0)
{
//申请新结点
p = (struct stud_node*)malloc(sizeof(struct stud_node));
//赋值新结点
scanf("%s %d",p->name,&p->score);
p->num=num;
p->next=NULL; //新结点的下一个结点指空
//判断是否为首结点,是则直接赋值,不是则尾接
if(tail==NULL)
head=p;
else
{
tail->next=p;
}
tail=p; //尾指针移动
scanf("%d",&num);
}
return head;
}
struct stud_node *deletelist( struct stud_node *head, int min_score )
{
//删除成绩低于min_score的学生,返回头指针
struct stud_node *move,*front;
move=head;
front=NULL;
while(move)
{
//若符合小于min_score
if(move->score<min_score)
{
//若为第一个,则移动头指针后移一位
if(front==NULL)
head=head->next;
//若非第一位则,move的前一个节点指向move的后一个节点,跳过move
else
front->next=move->next;
}//不符合则front移动到当前move的位置 保留前一个结点做标记
else
front=move;
//move向下一个结点移动
move=move->next;
}
return head;
}
本题要求实现一个函数,按输入数据的逆序建立一个链表。
struct ListNode *createlist();
函数createlist
利用scanf
从输入中获取一系列正整数,当读到−1时表示输入结束。按输入数据的逆序建立一个链表,并返回链表头指针。链表节点结构定义如下:
struct ListNode {
int data;
struct ListNode *next;
};
#include
#include
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *createlist();
int main()
{
struct ListNode *p, *head = NULL;
head = createlist();
for ( p = head; p != NULL; p = p->next )
printf("%d ", p->data);
printf("\n");
return 0;
}
/* 你的代码将被嵌在这里 */
1 2 3 4 5 6 7 -1
7 6 5 4 3 2 1
struct ListNode *createlist()
{
int data;
struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode)); //创建一个空的头结点
struct ListNode *insert;
head->next=NULL; //头指针指空
insert=head; //建立一个指针指向头结点
scanf("%d",&data);
while(data!=-1)
{
struct ListNode *p = (struct ListNode*)malloc(sizeof(struct ListNode)); //申请新结点
p->data=data;
//头插法核心
p->next=insert->next; //新节点指向头指针的下一个节点
insert->next=p; //头指针指向新节点
scanf("%d",&data);
}
return head->next; //返回的不是头指针而是首个结点,既头指针指向的下一个结点
}
本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中偶数值的结点删除。链表结点定义如下:
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *createlist();
struct ListNode *deleteeven( struct ListNode *head );
函数createlist
从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数deleteeven
将单链表head
中偶数值的结点删除,返回结果链表的头指针。
#include
#include
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *createlist();
struct ListNode *deleteeven( struct ListNode *head );
void printlist( struct ListNode *head )
{
struct ListNode *p = head;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
struct ListNode *head;
head = createlist();
head = deleteeven(head);
printlist(head);
return 0;
}
/* 你的代码将被嵌在这里 */
1 2 2 3 4 5 6 7 -1
1 3 5 7
/* 你的代码将被嵌在这里 */
struct ListNode *createlist()
{
struct ListNode *head=NULL,*p,*last;
int n;
last=head; //last指针用于移动表示链表末尾
do{
scanf("%d",&n); //输入结点数值
if(n!=-1)
{
p=(struct ListNode *)malloc(sizeof(struct ListNode)); //申请新节点
p->data=n; //新节点赋值
p->next=NULL; //新节点指空
if(last==NULL) //若为头结点时
head=p;
else
last->next=p; //非头结点时,尾接
last=p; //标志位移动到新节点处
}
else
break;
}while(n!=-1);
return head;
}
struct ListNode *deleteeven( struct ListNode *head )
{
//删除偶数结点
struct ListNode *move,*front;
move=head;
front=NULL;
while(move)
{
//若符合data为偶数
if((move->data)%2==0)
{
//若为第一个,则移动头指针后移一位
if(front==NULL)
head=head->next;
//若非第一位则,move的前一个节点指向move的后一个节点,跳过move
else
front->next=move->next;
}//不符合则front移动到当前move的位置 保留前一个结点做标记
else
front=move;
//move向下一个结点移动
move=move->next;
}
return head;
}
本题要求实现一个合并两个有序链表的简单函数。链表结点定义如下:
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);
其中list1
和list2
是用户传入的两个按data
升序链接的链表的头指针;函数mergelists
将两个链表合并成一个按data
升序链接的链表,并返回结果链表的头指针。
#include
#include
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *createlist(); /*裁判实现,细节不表*/
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);
void printlist( struct ListNode *head )
{
struct ListNode *p = head;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
struct ListNode *list1, *list2;
list1 = createlist();
list2 = createlist();
list1 = mergelists(list1, list2);
printlist(list1);
return 0;
}
/* 你的代码将被嵌在这里 */
1 3 5 7 -1
2 4 6 -1
1 2 3 4 5 6 7
/* 你的代码将被嵌在这里 */
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2)
{
//函数mergelists将两个链表合并成一个按data升序链接的链表 --合并---升序
//思路1.是相当于删除后一个链表的结点,在插入到前一个链表里。
//思路2,先合并两个链表,在利用指针变量做若干次冒泡排序。
if(list1==NULL&&list2)
return list2;
if(list2==NULL&&list1)
return list1;
if(list1==NULL&&list2==NULL)
return NULL;
struct ListNode *move1,*move2,*save,*front; //move1.2 分别用于移动,save用来指向从list2取下结点的地址
move2=list2;
move1=list1;
while(move2)
{
//<---取结点--->
save=move2; //保存list2当前节点
move2=move2->next; //list2首结点后移
save->next=NULL; //当前节点指空 ,取下结点
//<---插入结点到符合条件位置--->
//重置move1首结点地址,front指针
move1=list1;
front=NULL;
while(move1)
{
if(save->data<move1->data)
{
if(front)
{
//头插法核心 ,当data的值在list1中间时
save->next=front->next;
front->next=save;
break;
}else{
//当data的值比list1所有值都小的时候
save->next=list1;
list1=save;
break;
}
}else
front=move1;
move1=move1->next;
}
//尾插法 当data的值比list1所有值都大的时候
if(move1==NULL)
{
front->next=save;
}
}
//返回list1首地址
return list1;
}
本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中奇数值的结点重新组成一个新的链表。链表结点定义如下:
struct ListNode {
int data;
ListNode *next;
};
struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );
函数readlist
从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数getodd
将单链表L
中奇数值的结点分离出来,重新组成一个新的链表。返回指向新链表头结点的指针,同时将L
中存储的地址改为删除了奇数值结点后的链表的头结点地址(所以要传入L
的指针)。
#include
#include
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );
void printlist( struct ListNode *L )
{
struct ListNode *p = L;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
struct ListNode *L, *Odd;
L = readlist();
Odd = getodd(&L);
printlist(Odd);
printlist(L);
return 0;
}
/* 你的代码将被嵌在这里 */
1 2 2 3 4 5 6 7 -1
1 3 5 7
2 2 4 6
/* 你的代码将被嵌在这里 */
struct ListNode *readlist()
{
struct ListNode *head=NULL,*p,*last;
int n;
last=head; //last指针用于移动表示链表末尾
do{
scanf("%d",&n); //输入结点数值
if(n!=-1)
{
p=(struct ListNode *)malloc(sizeof(struct ListNode)); //申请新节点
p->data=n; //新节点赋值
p->next=NULL; //新节点指空
if(last==NULL) //若为头结点时
head=p;
else
last->next=p; //非头结点时,尾接
last=p; //标志位移动到新节点处
}
else
break;
}while(n!=-1);
return head;
}
struct ListNode *getodd( struct ListNode **L )
{
//奇数分离构成新链表,返回删除奇数的链表的头结点
struct ListNode *odd=NULL,*last,*p,*q,*k;
last=odd; //用于奇数链表链表 插入新节点
p=*L; //表示原链表移动指针
q=NULL; //q初始化,作为原链表移动指针前一个节点的标记
while(p)
{
if((p->data)%2) //data取余2为 1 则为奇数,删除节点
{
if(q&&p!=*L) //非L收个节点就是奇数的情况
{
k=p; //保存奇数节点
q->next=p->next; //删除奇数节点
if(last!=NULL) //插入odd链表
last->next=k;
else
odd=k;
last=k;
}
else //L的第一个就是奇数的情况
{
k=p; //保存奇数节点
*L=p->next; //头结点向后移动,删除奇数节点
if(last!=NULL) //插入odd链表
last->next=k;
else
odd=k;
last=k;
}
}
else
q=p; //未找到奇数节点,则用q保留当前位置
p=p->next; //p指针继续向下移动
if(last) //odd链表非空则
last->next=NULL; //odd末尾指针指空
}
return odd;
}
本题要求实现一个函数,统计学生学号链表中专业为计算机的学生人数。链表结点定义如下:
struct ListNode {
char code[8];
struct ListNode *next;
};
这里学生的学号共7位数字,其中第2、3位是专业编号。计算机专业的编号为02。
int countcs( struct ListNode *head );
其中head
是用户传入的学生学号链表的头指针;函数countcs
统计并返回head
链表中专业为计算机的学生人数。
#include
#include
#include
struct ListNode {
char code[8];
struct ListNode *next;
};
struct ListNode *createlist(); /*裁判实现,细节不表*/
int countcs( struct ListNode *head );
int main()
{
struct ListNode *head;
head = createlist();
printf("%d\n", countcs(head));
return 0;
}
/* 你的代码将被嵌在这里 */
1021202
2022310
8102134
1030912
3110203
4021205
#
3
int countcs( struct ListNode *head )
{
//统计并返回head链表中专业为计算机的学生人数
int i,count=0,item;
struct ListNode *p=head;
//p指针用来遍历链表
while(p)
{
//只读取code数组下标为1.2的字符
for(item=0,i=1;i<=2;i++)
{
//字符转整数
item=item*10+(p->code[i]-'0');
}
//判断是否为2
if(item==2)
{
count++;
}
//移动指针
p=p->next;
}
//返回计数
return count;
}
本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中所有存储了某给定值的结点删除。链表结点定义如下:
struct ListNode {
int data;
ListNode *next;
};
struct ListNode *readlist();
struct ListNode *deletem( struct ListNode *L, int m );
函数readlist
从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数deletem
将单链表L
中所有存储了m
的结点删除。返回指向结果链表头结点的指针。
#include
#include
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *readlist();
struct ListNode *deletem( struct ListNode *L, int m );
void printlist( struct ListNode *L )
{
struct ListNode *p = L;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
int m;
struct ListNode *L = readlist();
scanf("%d", &m);
L = deletem(L, m);
printlist(L);
return 0;
}
/* 你的代码将被嵌在这里 */
10 11 10 12 10 -1
10
11 12
struct ListNode *readlist()
{
//---**尾插法**---
//定义3个指针变量
//head用于返回链表的首结点,先初始化指空
//p 用于申请新节点
//last 用于连接head和新节点的一个尾指针,并且每次都停留在链表结尾
struct ListNode *head=NULL,*p,*last;
int n;
//先把last指向head ,起始时首尾都在一起
last=head;
do{
//输入节点信息
scanf("%d",&n);
//输入值!= -1时 操作
if(n!=-1)
{
//---申请新节点---
p=(struct ListNode *)malloc(sizeof(struct ListNode));
p->data=n;
p->next=NULL; //申请的新节点初始化,下一个节点指空
//---连接节点----
//head需要返回,不能用来移动,当检测到尾指针指空,表示首尾指针并未有任何值
if(last==NULL)
head=p; //直接把第一个节点赋值到head
else
last->next=p; //若last非空 则把p连接到last后一个节点 head->last->p->null;
last=p; //连接完后last移动到到p上,既移动到新的结尾 head->last->p1->last(p)->null;
}
else
break;
}while(n!=-1);// -1结束循环
return head;
}
struct ListNode *deletem( struct ListNode *L,int m )
{
//--由于单链表遍历是不可逆的---
//设置两个指针一个控制移动,一个用于连接(防止断链)
struct ListNode *p,*q;
p=L; //p用于移动
q=NULL; //q初始化
//当p非空时
while(p)
{
//若data为m
if(p->data==m)
{
//情况1:中间节点或者末尾节点是m ,此时 q!=NULL
if(q)
q->next=p->next; //q->m(p)->x q->x
//情况2:首节点就是m ,此时 q=NULL
else
L=p->next; //则直接移动链表的首结点后移
}
else//data不为m,则q移动到p当前位置,相当于记录p前一个节点
q=p;
//p指针移动到下一个节点
p=p->next;
}
return L;
}
本题要求实现一个函数,将给定单向链表逆置,即表头置为表尾,表尾置为表头。链表结点定义如下:
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *reverse( struct ListNode *head );
其中head
是用户传入的链表的头指针;函数reverse
将链表head
逆置,并返回结果链表的头指针。
#include
#include
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *createlist(); /*裁判实现,细节不表*/
struct ListNode *reverse( struct ListNode *head );
void printlist( struct ListNode *head )
{
struct ListNode *p = head;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
struct ListNode *head;
head = createlist();
head = reverse(head);
printlist(head);
return 0;
}
/* 你的代码将被嵌在这里 */
1 2 3 4 5 6 -1
6 5 4 3 2 1
struct ListNode *reverse( struct ListNode *head )
{
//时间复杂度为O(n),空间复杂度为O(1)
//特殊情况,空链表
if(head==NULL)
return NULL;
//申请一个空的结点作为头结点
struct ListNode *fake = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *front,*now,*tail;
fake->next=head;
front=head;
//当now==NULL时,结束循环
do{
//指针移动
now=front->next;
if(now==NULL)
break;
tail=now->next;
//头插法
front->next=tail;
now->next=fake->next;
fake->next=now;
}while(1);
return fake->next;
}
完结
总结:(待续)