目录
1. (程序题)创建单链表
2. (程序题)删除单链表重复节点
3. (程序题)求单链表中间结点
4. (程序题)单链表交换两节点
5. (程序题)单链表存储法雷序列
6. (程序题)合并单链表
7. (程序题)排序单链表
1. (程序题)
题目编号:Exp09-Basic01
题目名称:创建单链表
题目描述:请填写缺失代码完成程序,实现如下功能:
根据从键盘随机输入以0结束的若干非零整数,建立一个单链表;之后将此链表中保存的数字顺次输出,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符;若是空链表,则输出NULL。
例如,
输入:5 4 2 1 3 0
输出:5 4 2 1 3
输入:0 5 4 2 1 3 0
输出:NULL
#include <stdio.h>
#include <malloc.h>
struct cell { //单链表结点结构体定义
int x;
struct cell* next;
};
struct cell* build(void) { //新建单链表,并将建好的单链表首结点地址返回
struct cell* head, * tmp, * p;
head = tmp = p = NULL;
int n;
scanf("%d", &n);
if (n == 0)
return NULL;
head = (struct cell*)malloc(sizeof(struct cell));
head->x = n;
scanf("%d", &n);
p = head;
while (n != 0) {
tmp=(struct cell*)malloc(sizeof(struct cell));
tmp->x = n;
p->next = tmp;
p = tmp;
p->next = NULL;
scanf("%d", &n);
}
return head;//返回单链表头
}
void print(struct cell* head) {//打印整个单链表,head是指向单链表首结点的指针
struct cell* p;
p = head;
printf("%d", p->x);
p = p->next;
while (p != NULL) {
printf(" %d", p->x);
p = p->next;
}
}
void release(struct cell* head) {//释放单链表空间,head是指向单链表首结点的指针
struct cell* p;
while(head!=NULL){
p = head;
head = p->next;
free(p);
}
}
int main(void) {
struct cell* head;
head = build();
if (head != NULL)
print(head);
else
printf("NULL");
release(head);
}
2. (程序题)
题目编号:Exp09-Basic02,GJBook3-13-06
题目名称:删除单链表重复结点
题目描述:请填写缺失代码完成程序,实现如下功能:
首先根据键盘随机输入,以0结束的若干非零整数建立单链表;然后删除此链表中值重复的结点仅保留一个,且不改变原有结点顺序;最后将删除后链表中各结点值输出,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符;若是空链表,则输出NULL。
例如,
输入:5 4 2 1 3 0
输出:5 4 2 1 3
输入: 4 2 1 3 3 2 0
输出:4 2 1 3
输入: 0 4 2 3 2 0
输出:NULL
#include <stdio.h>
#include <malloc.h>
struct cell {//单链表结点结构体定义
int x;
struct cell* next;
};
struct cell* build(void) {//新建单链表,并将建好的单链表首结点地址返回
struct cell* head, * tmp, * p;
head = tmp = p = NULL;
int n;
scanf("%d", &n);
if (n == 0)
return NULL;
head = (struct cell*)malloc(sizeof(struct cell));
head->x = n;
scanf("%d", &n);
p = head;
while (n != 0) {
tmp = (struct cell*)malloc(sizeof(struct cell));
tmp->x = n;
p->next = tmp;
p = tmp;
p->next = NULL;
scanf("%d", &n);
}
return head;//返回单链表头
}
struct cell* del2one(struct cell* head) {//删除重复结点只保留一个,head是单链表首结点指针
struct cell* p,*p0,*r; //r指向p0之前的节点,p0指向待比较的节点
p = head;
while (p != NULL) {
r = p;
p0 = p->next;
while (p0 != NULL) {
if (p0->x == p->x) { //当有重复元素
r->next = p0->next;
p0 = r ->next;
}
else {
r = r->next;
p0 = r->next;
}
}
p = p->next;
}
return head;//返回删除重复结点的单链表头
}
void print(struct cell* head) {//打印整个单链表,head是单链表首结点指针
struct cell* p;
printf("%d", head->x);
p = head->next;
while (p != NULL) {
printf(" %d", p->x);
p = p->next;
}
}
void release(struct cell* head) {//释放单链表空间,head是单链表首结点指针
struct cell* p;
while (head != NULL) {
p = head;
head = p->next;
free(p);
}
}
int main(void) {
struct cell* head;
head = build();
head = del2one(head);
if (head != NULL)
print(head);
else
printf("NULL");
release(head);
}
3. (程序题)
题目编号 :Exp09-Basic03
题目名称:求单链表中间结点
题目描述:请填写缺失代码完成程序,实现如下功能:
首先根据键盘随机输入,以0结束的若干非零整数建立单链表;
然后寻找处于链表中间位置的结点,若中间结点有两个,则设定前一个为中间位置结点;
最后将从中间结点开始到链表尾各结点值输出,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符。
若是空链表,则输出NULL。
例如,
输入:5 4 2 1 3 0
输出:2 1 3
输入: 4 2 1 3 3 2 0
输出:1 3 3 2
#include <stdio.h>
#include <malloc.h>
struct cell {//单链表结点结构体定义
int x;
struct cell* next;
};
struct cell* build(void) {//新建单链表,并将建好的单链表首结点地址返回
struct cell* head, * tmp, * p;
head = tmp = p = NULL;
int n;
scanf("%d", &n);
if (n == 0)
return NULL;
head = (struct cell*)malloc(sizeof(struct cell));
head->x = n;
p = head;
p->next = NULL;
scanf("%d", &n);
while (n != 0) {
tmp = (struct cell*)malloc(sizeof(struct cell));
tmp->x = n;
p->next = tmp;
p = tmp;
p->next = NULL;
scanf("%d", &n);
}
return head;//返回单链表头
}
struct cell* mid(struct cell* head) {//寻找链表中间位置结点地址并返回,head是单链表首结点指针
int i=0,n;
struct cell* p;
p = head;
while (p != NULL) {
i++;
p = p->next;
}
if (i % 2 == 0)
n = i / 2 - 1;
else
n = i / 2;
p = head;
while (n != 0) {
p = p->next;
n--;
}
head = p;
return head;
}
void print(struct cell* head) {//打印整个单链表,head是单链表首结点指针
struct cell* p;
printf("%d", head->x);
p = head->next;
while (p->x != 0) {
printf(" %d", p->x);
p = p->next;
}
}
void release(struct cell* head) {//释放单链表空间,head是单链表首结点指针
struct cell* p;
while (head != NULL) {
p = head;
head = p->next;
free(p);
}
}
int main(void) {
struct cell* head, * half;
head = build();
half = mid(head);
if (half != NULL)
print(half);
else
printf("NULL");
release(head);
}
4. (程序题)
题目编号:Exp09-Basic04
题目名称:单链表交换两结点
题目描述:请填写缺失代码完成程序,实现如下功能:
首先根据键盘随机输入,以0结束的若干非零整数建立单链表;
然后根据输入的两个索引位置交换链表上的两个结点(链表首元素索引为1,且要交换的两个索引位置不相邻);
最后链表各结点值输出,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符。
若是空链表,则输出NULL。
例如,
输入:1 2 3 4 5 6 0 1 5
输出:5 2 3 4 1 6
输入:0 1 2 3 4 5 6 0 1 5
输出:NULL
#include <stdio.h>
#include <malloc.h>
struct cell {//单链表结点结构体定义
int x;
struct cell* next;
};
struct cell* build(void) {//新建单链表,并将建好的单链表首结点地址返回
struct cell* head, * tmp, * p;
head = tmp = p = NULL;
int n;
scanf("%d", &n);
if (n == 0)
return NULL;
head = (struct cell*)malloc(sizeof(struct cell));
head->x = n;
p = head;
p->next = NULL;
scanf("%d", &n);
while (n != 0) {
tmp= (struct cell*)malloc(sizeof(struct cell));
tmp->x = n;
p->next = tmp;
p = tmp;
p->next = NULL;
scanf("%d", &n);
}
return head;//返回单链表头
}
struct cell* swap(struct cell* head, int m, int n) {//交换索引为m和n的两个结点,head是单链表首结点指针
if (head == NULL) return NULL;
struct cell* pm = head, * pn = head;
struct cell* pm0 = NULL, * pn0 = NULL;
struct cell* tmp;
int i;
for (i = 1; i < m && pm != NULL; i++) {
pm0 = pm;
pm = pm->next;
}
for (i = 1; i < n && pn != NULL; i++) {
pn0 = pn;
pn = pn->next;
}
if (pm != NULL && pn != NULL && m != n) {//索引为m,n的结点位于链表中间
if (pm0 != NULL && pn0 != NULL) {
tmp = pn->next;
pm0->next = pn;
pn->next = pm->next;
pn0->next = pm;
pm->next = tmp;
}
if (pm0 == NULL && pn0 != NULL) { //即pm为head
tmp = pm->next;
pn0->next = pm;
pm->next = pn->next;
pn->next = tmp;
head = pn;
}
if (pm0 != NULL && pn0 == NULL) { //pn为head
tmp = pn->next;
pn->next = pm->next;
pm0->next = pn;
pm->next = tmp;
head = pm;
}
}
return head;
}
void print(struct cell* head) {//打印整个单链表,head是单链表首结点指针
struct cell* p;
printf("%d", head->x);
p = head->next;
while (p->x != 0) {
printf(" %d", p->x);
p = p->next;
}
}
void release(struct cell* head) {//释放单链表空间,head是单链表首结点指针
struct cell* p;
while (head != NULL) {
p = head;
head = p->next;
free(p);
}
}
int main(void) {
struct cell* head;
int m, n;
head = build();
scanf("%d%d", &m, &n);
head = swap(head, m, n);
if (head != NULL)
print(head);
else
printf("NULL");
release(head);
}
5. (程序题)
题目编号 :Exp09-Basic05,GJBook3例-13-04
题目名称:单链表存储法雷序列
题目描述:请填写缺失代码完成程序,实现如下功能:
给定一个正整数n,用单链表递增存储n阶法雷序列各项值。n阶法雷序列是把所有不可约分的分数j/i(0<i≤n; 0≤j≤i)递增排序的序列。
输入一个正整数n;输出n阶法雷序列各项分数形式,分数的分子和分母间以/连接,各个分数间以一个西文空格间隔,最后一个数字后无任何字符。若是空链表或n不符合要求,则输出NULL。
例如,
输入:3
输出:0/1 1/3 1/2 2/3 1/1
这个就是教材上面的程序,完全按照上面的思路来的orz
#include <stdio.h>
#include <malloc.h>
struct farlei_item {
int numerator, denominator; // 分子、分母
struct farlei_item* next; // 连接部分
};
typedef struct farlei_item* farleipointer;
int gcd(int x, int y) { /* 求最大公约数 */
if (y == 0)
return x;
else
return gcd(y, x % y);
}
/*构造法雷序列,并返回序列头指针*/
farleipointer farlei(int n) {
int i, j;
farleipointer fn, r, r0, p;
fn = r = r0 = p = NULL;
if (n < 1)
return NULL; //如果n<=0,则没有法雷序列
fn = (farleipointer)malloc(sizeof(struct farlei_item)); //构造0/1
fn->numerator = 0;
fn->denominator = 1;
p = (farleipointer)malloc(sizeof(struct farlei_item)); //构造1/1
p->numerator = 1;
p->denominator = 1;
fn->next = p;
p->next = NULL;
for (i = 2; i <= n; i++)
for (j = 1; j < i; j++)
if (gcd(i, j) == 1) {
r = fn;
while (j * r->denominator > i * r->numerator) {
r0 = r; r = r->next;
}//j/i插入到r0,r之间
p= (farleipointer)malloc(sizeof(struct farlei_item));
p->numerator = j;
p->denominator = i;
r0->next = p;
p->next = r;
}
return fn;
}
void print(farleipointer fn) {//输出fn引导的法雷序列
farleipointer p;
p = fn;
printf("%d/%d", p->numerator, p->denominator);
p = p->next;
while (p != NULL) {
printf(" %d/%d", p->numerator, p->denominator);
p = p->next;
}
}
void release(farleipointer head) {//释放单链表空间,head是单链表首结点指针
farleipointer p;
while(head!=NULL){
p = head;
head = p->next;
free(p);
}
}
int main(void) {
int n;
farleipointer fn;
scanf("%d", &n);
fn = farlei(n); //生成n级法雷序列
if (fn != NULL)
print(fn);
else
printf("NULL");
release(fn);
return 0;
}
6. (程序题)
题目编号:Exp09-Enhance03
题目名称:合并单链表
题目描述:请填写缺失代码完成程序,实现如下功能:
首先从键盘输入一行以0结束的若干非零整数,建立一个单链表,输入的整数顺序为数字非递减顺序;
然后以同样的方式,仍在第一行继续输入并建立第二个单链表;
之后将两个链表合并形成一个新链表,使得新链表依然保持数字非递减顺序;
最后验证输出新链表所有值,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符。若是空链表,则输出NULL。
例如,
输入:2 3 4 4 5 6 0 1 3 4 6 7 0
输出:1 2 3 3 4 4 4 5 6 6 7
输入:0 0
输出:NULL
#include <stdio.h>
#include <malloc.h>
struct cell {//单链表结点结构体定义
int x;
struct cell* next;
};
struct cell* build(void) {//新建单链表,并将建好的单链表首结点地址返回
struct cell* head, * tmp, * tail;
head = tmp = tail = NULL;
int n, i;
scanf("%d", &n);
if (n == 0)
return NULL;
head = (struct cell*)malloc(sizeof(struct cell));
head->x = n;
tail = head;
tail->next = NULL;
scanf("%d", &n);
while (n != 0) {
tmp = (struct cell*)malloc(sizeof(struct cell));
tmp->x = n;
tail->next = tmp;
tail = tmp;
tail->next = NULL;
scanf("%d", &n);
}
return head;//返回单链表头
}
struct cell* combine(struct cell* p, struct cell* q) {//合并两个链表p和q
struct cell* head = NULL, * p0 = NULL, * q0 = NULL, * r = NULL;
if (p == NULL && q != NULL) return q;
if (p != NULL && q == NULL) return p;
if (p == NULL && q == NULL) return NULL;
head = p;//head当头指针
q0 = q;
while (q0 != NULL) {
p = head;
r = q0; //r保存要插入的结点
q = q->next; //q的头指针指向下一个
if (p->x < r->x) {
p0 = p;
p = p->next;
while (p->x < r->x && p->next != NULL) {
p0 = p;
p = p->next;
}
if (p->next == NULL) {
p->next = r;
r->next = NULL;
}
else {
r->next = p;
p0->next = r;
}
}
else {
r->next = p;
head = r;
}
q0 = q;
}
return head;
}
void print(struct cell* head) {//打印整个单链表,head是单链表首结点指针
struct cell* p;
printf("%d", head->x);
p = head->next;
while (p != NULL) {
printf(" %d", p->x);
p = p->next;
}
}
void release(struct cell* head) {//释放单链表空间,head是单链表首结点指针
struct cell* p;
while (head != NULL) {
p = head;
head = p->next;
free(p);
}
}
int main(void) {
struct cell* head1, * head2, * result;
head1 = build();
head2 = build();
result = combine(head1, head2);
if (result != NULL)
print(result);
else
printf("NULL");
release(result);
return 0;
}
7. (程序题)
题目编号:Exp09-Enhance04,GJBook3例-13-02
题目名称:排序单链表
题目描述:请填写缺失代码完成程序,实现如下功能:
首先根据键盘随机输入一行以0结束的若干非零整数建立单链表;
然后递增排序链表;
最后验证输出排序后链表中所有值,相邻数字间以一个西文空格间隔,最后一个数字后无任何字符。
若是空链表,则输出NULL。
例如,
输入:2 3 6 4 5 0
输出:2 3 4 5 6
输入:0 2 3 4
输出:NULL
(排序第一次自己写的太复杂了,借鉴了一下别人的思路orz)
#include <stdio.h>
#include <malloc.h>
struct cell {//单链表结点结构体定义
int x;
struct cell* next;
};
struct cell* build(void) {//新建单链表,并将建好的单链表首结点地址返回
struct cell* head, * tmp, * tail;
head = tmp = tail = NULL;
int n;
scanf("%d", &n);
if (n == 0)
return NULL;
head = (struct cell*)malloc(sizeof(struct cell));
head->x = n;
tail= head;
tail->next = NULL;
scanf("%d", &n);
while (n != 0) {
tmp = (struct cell*)malloc(sizeof(struct cell));
tmp->x = n;
tail->next = tmp;
tail = tmp;
tail->next = NULL;
scanf("%d", &n);
}
return head;//返回单链表头
}
struct cell* sort(struct cell* head) {//递增排序链表,head是单链表首结点指针
struct cell* p, * p0, * r, * r0, * q;
p = p0 = r = r0 = q = NULL;
p = head;
p = p->next;
p0 = head;
while(p!=NULL){
r = head;
while (r->x < p->x && r != p) {
r0 = r;
r = r->next;
}
if (r != p) { //r0比p小,r比p大
q = p; //此处把p所指的结点保存,根据r的位置分情况
p0->next = p->next;
p = p0;
if (r == head) {
q->next = r;
head = q;
}
else { //将q插入r0与r之间
q->next = r;
r0->next = q;
}
}
p0 = p;
p = p->next;
}
return head;
} /* sort */
void print(struct cell* head) {//打印整个单链表,head是单链表首结点指针
struct cell* p;
printf("%d", head->x);
p = head->next;
while (p->x != 0) {
printf(" %d", p->x);
p = p->next;
}
}
void release(struct cell* head) {//释放单链表空间,head是单链表首结点指针
struct cell* p;
while (head != NULL) {
p = head;
head = p->next;
free(p);
}
}
int main(void) {
struct cell* head;
head = build();
if (head != NULL) {
head = sort(head);
print(head);
}
else
printf("NULL");
release(head);
return 0;
}