1、C语言-文件操作
1、编制一个将文本中的全部信息送往显示屏上显示的程序,文件名由main函数命令行给出。
c
# include<stdio.h>
# include<stdlib.h>
/*
解题思路:首先定义一个存放文件名的字符数组fileneme[],然后输入文件的名字,fopen()函数打开文件
如果文件不存在则返回错误信息
如果文件存在则打开该文件 ,并用fgetc函数,从文件中读取一个字符,存储到ch中
结束的标志是 ( ch = fgetc(fp) ) != EOF,然后再用fputc函数将文件中的信息在显示屏上显示
最后再用fclose()函数将文件关闭
*/
int main(){
FILE *fp; // 定义文件指针
char ch;
char filename[20]; //用于存储输入的文件名
printf("请输入一个文件名称:");
scanf("%s",filename); // 输入一个文件名
fp = fopen(filename,"r"); // 打开文件
if(fp == NULL){
printf("文件不存在");
exit(0);
}
while((ch = fgetc(fp)) !=EOF ) {
fputc(ch,stdout); // 输出到显示屏
// fputc(ch,fp);
// putchar(ch);
}
fclose(fp);
return 0;
}
2、数据结构-线性表
2、从一维数组存储结构实现线性表就地逆置算法,即将(a1,a2,a3,a4,......an)逆置为(an,an-1,an-2,......,a2,a1),假设线性表
存储在数组a[m]的前n个位置中,m>n。
c
/*
解题思路:
将第一个元素和最后一个元素交换,
将第二个元素和倒数第二个元素交换
依次类推,直到将所有的元素交换到指定的位置
完成线性表的就地逆置
*/
void reserve(int &a[],int n) { // n表示元素个数
int temp;
for(int i = 0;i<n/2;i++){
temp = a[i]; // 将元素交换
a[i] = a[n-1-i];
a[n-1-i] = temp;
}
}
3、数据结构-合并两个链表
3、假设有两个按元素值递增有序排列的线性表A和B,均以链表作为存储结构,请设置一个算法,将A和B表合并成一个按元素值递
增有序(元素值可相同)排列的线性表C,并利用A表和B表的结点空间存放表C。
方法一:头插法
c
# include<stdio.h>
//单链表的定义
typedef struct LNode {
ELemType data;
LNode *next;
} LNode,*LinkList;
/*
解题思路:假设A,B带有头指针,定义pa,pb指针分别指向A,B的下一个结点,
在定义一个r指针,指向 pa/pb的下一个结点,防止断链
定义一个C结点指向A,将C置空,从新存储排好序的结点
运用头插法,先将A,B中较大的元素插入C中,实现整体按元素值递增有序;
因为A,B链表中的结点个数不一样,
所以当A中的结点数更少时 ,将B中的元素依次加入C中
反之,则将A中的元素依次加入C中
*/
LinkList Merge(LNode &A,LNode &B) {
LNode *pa = A->next;
LNode *pb = B->next;
LNode *r; // 标记指针,防止断链,指向 pa/pb的下一个结点
LNode *C = A;
C->next == NULL; // 将原来的A链表置空,用来存储从新组合的链表 C
while(pa&&pb) { //
if(pa->data > pb->data) { // 运用头插法将大的元素率先加入C链表中
r = pa->next;
pa->next = C->next;
C->next = pa;
pa = r;
} else {
r = pb->next;
pb->next = C->next;
C->next = pb;
pb = r;
}
}
while(pa) {
r = pa->next;
pa->next = C->next;
C->next = pa;
pa = r;
}
while(pb) {
r = pb->next;
pb->next = C->next;
C->next = pb;
pb = r;
}
return C;
}
方法二:尾插法
c
# include<stdio.h>
//单链表的定义
typedef struct LNode {
ELemType data;
LNode *next;
} LNode,*LinkList;
/*
解题思路:假设A,B带有头指针,定义pa,pb指针分别指向A,B的下一个结点,
在定义一个u指针
定义一个C结点指向A,将C置空,从新存储排好序的结点
运用尾插法,先将A,B中较小的元素插入C中,实现整体按元素值递增有序;
因为A,B链表中的结点个数不一样,
所以当A中的结点数更少时 ,将B中的元素依次加入C中
反之,则将A中的元素依次加入C中
*/
LinkList Merge(LNode &A,LNode &B) {
LNode *pa = A->next;
LNode *pb = B->next;
LNode *u; //
LNode *C = A;
C->next == NULL; // 将原来的A链表置空,用来存储从新组合的链表 C
while(pa&&pb) { //
if(pa->data <= pb->data) { // 运用尾插法将小的元素率先加入C链表中
u = pa;
C->next = pa;
C = pa;
pa = pa->next;
free(u);
} else {
u = pb;
C->next = pb;
C = pb;
pb = pb->next;
free(u);
}
}
while(pa) {
u = pa;
C->next = pa;
C = pa;
pa = pa->next;
free(u);
}
while(pb) {
u = pb;
C->next = pb;
C = pb;
pb = pb->next;
free(u);
}
return C;
}
4、数据结构-二叉树遍历
4、已知二叉树先序遍历序列为 ABCDEFG,中序遍历为 CBEFDGA,试画出此二叉树,并给出后序遍历。
bash
# 后续遍历:C F E G D B A
A
B
C D
E G
F
5、C语言-选择排序
5、用C语言写一个函数,实现简单选择排序算法,并根据算法给出下列关键字序列 14 、4、76、27、22、98、11 按从小到大的
排序过程。
c
/**
第一躺:4 14 76 27 22 98 11
第二躺:4 11 76 27 22 98 14
第三躺:4 11 14 27 22 98 76
第四躺:4 11 14 22 27 98 76
第五躺:4 11 14 22 27 76 98
*/
/*
解题思路:简单选择排序思想就是每一趟排序从序列中跳出最小的元素放到前面来
第1趟从整个序列中选择关键字最小的元素放在第1位
第2趟从整个序列中选择关键字最小的元素放在第2位
第3趟从整个序列中选择关键字最小的元素放在第3位
...... 依次类推,直到整个序列关键字从小到大排序
*/
# include<stdio.h>
void swap(int a,int b){ // 交换两个元素
int temp;
temp = a;
a = b;
b = a;
}
// 简单选择排序
void SelectSort(int &A[],int n){
int i,j,min;
for(i = 0;i<n-1;i++){ // 找出最小元素的下标
min = i; // 假定下标是最小值下标
for(j = i+1;j<n;j++){ // 遍历后面的元素
if(A[min] > A[j]){ // 寻找真正的最小值下标
min = j;
}
}
if(min!=i){
swap(A[i],A[min]); // 将小的元素换过来
}
}
}
6、数据结构-二叉排序树
6、已知有8个小伙伴 zhao ,qian, sun, li , zhou , wu , zheng , wang,按照字典的顺序构造这8个人的二叉排序树,并给出查找wu所需的步数,要查找 ma ,要几步才知道 ma 在不在序列中 。
bash
# 解题思路:将序列构造成一个二叉排序树,二叉排序树的特点就是 左子树 < 根节点 < 右子树,其中序遍历元素是递增有序的
zhao
qian zhou
li sun zheng
wu
wang
#首先选 zhao 作为根节点,然后 qian 比 zhao 小,所有放在左子树,sun 比 zhao 小放在 zhao 的左子树,比 qian 大放在 qian 的右子树
#依次类推,直到构建成一个二叉排序树
# 所以查找 wu 需要4步,查找 ma 需要3步
7、C语言-最大公约数
7、用C语言编写两个程序,计算函数最大公约数一个用递归方式,一个用非递归方式。
c
/*
解题思路:最大公约数指的是两个或多个整数共有约数中最大的一个
采用的是欧几里得算法,也叫辗转相除法:就是将 a,b两个数取余数假设 t = a%b,然后将较小的元素 b 对t再取余数,直到最后余数为0,则最后依次取余数的 b就是最大公约数
*/
// 方法1、递归方法
// 最大公约数 递归:辗转相除法
int Gcd(int a,int b){
if(b>0){
return Gcd(b,a%b);
}else{
return a;
}
}
//方法2:非递归
int GCB2(int a,int b) {
int t;
while(b!=0) {
t = a%b;
a = b;
b = t;
}
return a;
}
// 主函数
int main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("最大公约数为:%d\n",Gcd(a,b));
printf("最大公约数为:%d\n",GCB2(a,b));
return 0;
}
8、数据结构-循环单链表转成循环双链表
8、假设有一个循环单链表,结点有三个域:pre data next,其中 data 为数据域,next 为指针域其值为后继节点的地址,pre 为
指针域,他的值为空(NULL),试编写算法,将此链表改为双循环链表。
c
/*
解题思路:定义两个工作指针,nextwork后继工作指针 ,prework前趋工作指针
然后给所有的结点添加指向前趋的指针,最后再处理头结点。
*/
// 单循环链表定义
typedef struct LNode{
ElemType data;
struct LNode *pre,*next;
}LNode,*LinkList;
void change(LinkList &L){
LNode *prework = L; // 前趋工作指针
LNode *nextwork = L->next; // 后继工作指针
while(nextwork!=L){
nextwork->pre = prework; // 指向前趋
nextwork = nextwork->next; // nextwork 后移
prework = prework->next; // prework后移
}
if(nextwork == L){ // 处理最后的头结点
L->pre = prework;
}
}