- NO.1 有序数组中插入数据(函数版)
- NO.2 删除数组元素
- NO.3 数组的排序
- NO.4 查成绩
NO.1 有序数组中插入数据(函数版)
有一个足够“大”的数组a,其中已经存储了n个呈升序排列的数据。调用函数insert(a, n, m),可以将数m插入到a中的合适位置,使其仍然保持升序,并且返回值为数组中有效数字的个数(即原先的n加1)。
例如,若a中数据为1 7 8 17 23 24 59 62 101,n=9,需要插入的数字m为50,调用函数insert(a, n, m)后,a中数据为1 7 8 17 23 24 50 59 62 101,n=10。
#include<stdio.h>
#define N 20
int insert(int a[],int,int);
int main()
{
int a[N]={1, 7, 8, 17, 23, 24, 59, 62, 101};
int i, n=9;
int m =50;
n = insert(a, n, m); //在长度为n的a数组中插入m,使仍保持有序
for(i=0; i<n; ++i)
printf("%d ", a[i]);
printf("\n");
return 0;
}
int insert(int a[],int n,int x)
{
int i=n;
while(a[i-1]>x)
{
a[i]=a[i-1];
i--;
}
a[i]=x;
return n+1;
}
执行结果
小结
本例中a[i]=a[i-1]; i--
不可合并为a[i--]=a[i-1]
,不然会影响结果。
NO.2 删除数组元素
del函数的作用是删除数组a中的指定元素x,n为数组a的元素个数。函数的返回值,为删除元素后的有效元素个数(数组中可能有重复元素)。函数的原型为:
int del (int a[10],int n,int x)
(1)请实现这个函数,并完成测试。
(2)如果在函数调用时,要求数组中的元素呈升序排列呢?
代码一
#include<stdio.h>
#define N 20
int del(int a[],int,int);
int main()
{
int a[N]={1, 7, 8, 50, 50, 24, 50, 59, 62, 101};
int i, n=10;
int m =50;
n = del(a, n, m); //在长度为n的a数组中删除m
for(i=0; i<n; ++i)
printf("%d ", a[i]);
printf("\n");
return 0;
}
int del(int a[],int n,int x)
{
int i,j=0;
for(i=0;i<n;i++)
if(a[i]!=x) //把不等于x的数放入数组,也就排除了x
a[j++]=a[i];
return j;
}
执行结果
小结一:
排除的数只有一个元素,那直接用元素前移法比较好;但如果排除的数是多个并且可能有相同元素时,直接提取非排除元素更好;思维不要被前移法固定了,总是去找那些要排除的元素,有时候逆向思维更方便。
代码二
#include<stdio.h>
#define N 20
int del(int a[],int,int);
int main()
{
int a[N]={1, 7, 8, 24, 50, 50, 50, 59, 62, 101};
int i, n=10;
int m =50;
n = del(a, n, m); //在长度为n的a数组中删除m
for(i=0; i<n; ++i)
printf("%d ", a[i]);
printf("\n");
return 0;
}
int del(int a[],int n,int x) //排除升序数组a[n]中的元素x
{
int *p=a,i;
for(i=0;i<n;i++)
{
if(a[i]==x) //指针指向第一个排除的元素单元
{
p=&a[i];
break;
}
}
while(p<a+n)
{
if((*p)!=x) //将排除元素后面的数据前移
a[i++]=*(p++);
else
p++;
}
return i;
}
执行结果
小结二
程序优化,当要删除的数不存在时,添加个输出语句,在del函数中的for循环结束后添加以下语句:
if(i>=n)
{
printf("no number!\n");
return i;
}
NO.3 数组的排序
(1)编写函数,完成冒泡排序
要求不能改变下面的main函数。
//两个函数bubble_sort和output_array的声明
int main( )
{
int a[20]={86,76,62,58,77,85,92,80,96,88,77,67,80,68,88,87,64,59,61,76};
int b[15]={27,61,49,88,4,20,28,31,42,62,64,14,88,27,73};
bubble_sort(a,20); //用冒泡法按降序排序a中元素
output_array(a,20); //输出排序后的数组
bubble_sort(b,15); //用冒泡法按降序排序b中元素
output_array(b,15); //输出排序后的数组
return 0;
}
//请在下面定义bubble_sort和output_array函数
(2)字符数组排序:改造(1)的程序,使其能对字符数组进行排序
int a[20]={...};
int b[15]={...};
改为
char a[20] = {'s','o','r','t','b','u','b','b','l','e','s','e','l','e','c','t','o','k','o','k'};
char b[15] = {'a','b','a',...}; //自己补足
(3)体验选择排序:改造(1)的程序,将bubble_sort(…)改为select_sort(…),排序算法由冒泡排序换作为选择排序,排序结果由降序变为升序,完成类似的任务。
代码一
#include<stdio.h>
//两个函数bubble_sort和output_array的声明
void bubble_sort(int a[],int);
void output_array(int a[],int);
int main( )
{
int a[20]={86,76,62,58,77,85,92,80,96,88,77,67,80,68,88,87,64,59,61,76};
int b[15]={27,61,49,88,4,20,28,31,42,62,64,14,88,27,73};
bubble_sort(a,20); //用冒泡法按降序排序a中元素
output_array(a,20); //输出排序后的数组
bubble_sort(b,15); //用冒泡法按降序排序b中元素
output_array(b,15); //输出排序后的数组
return 0;
}
//请在下面定义bubble_sort和output_array函数
void bubble_sort(int a[],int n)
{
int i,j,t;
for (i=0;i<n-1;i++)
for(j=0;j<n-1-i;j++)
if(a[j]<a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
void output_array(int a[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}
执行结果一:
代码二
#include<stdio.h>
//两个函数bubble_sort和output_array的声明
void bubble_sort(char a[],int);
void output_array(char a[],int);
int main( )
{
char a[20] = {'s','o','r','t','b','u','b','b','l','e','s','e','l','e','c','t','o','k','o','k'};
char b[15] = {'a','b','a','b','c','l','u','o','e','p','s','i','l','o','n'};
bubble_sort(a,20); //用冒泡法按降序排序a中元素
output_array(a,20); //输出排序后的数组
bubble_sort(b,15); //用冒泡法按降序排序b中元素
output_array(b,15); //输出排序后的数组
return 0;
}
//请在下面定义bubble_sort和output_array函数
void bubble_sort(char a[],int n)
{
int i,j;
char t;
for (i=0;i<n-1;i++)
for(j=0;j<n-1-i;j++)
if(a[j]<a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
void output_array(char a[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%c ",a[i]);
printf("\n\n");
}
执行结果二
代码三
#include<stdio.h>
//两个函数bubble_sort和output_array的声明
void select_sort(int a[],int);
void output_array(int a[],int);
int main( )
{
int a[20]={86,76,62,58,77,85,92,80,96,88,77,67,80,68,88,87,64,59,61,76};
int b[15]={27,61,49,88,4,20,28,31,42,62,64,14,88,27,73};
select_sort(a,20); //用选择排序法按升序排序a中元素
output_array(a,20); //输出排序后的数组
select_sort(b,15); //用选择排序法按升序排序b中元素
output_array(b,15); //输出排序后的数组
return 0;
}
//请在下面定义bubble_sort和output_array函数
void select_sort(int a[],int n)
{
int i,j,k,t;
for (i=0;i<n-1;i++) //n个元素需扫描n-1趟
{
k=i;
for(j=i+1;j<n;j++) //从i+1个开始遍历到结尾,需循环n-i-1次
if(a[j]<a[k])
k=j;
t=a[k];
a[k]=a[i];
a[i]=t;
}
}
void output_array(int a[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}
执行结果三
NO.4 查成绩
(1)score1.txt提供了某大学两个班某次测验的数据,包括每位同学的学号及成绩。
请编程序,输入学号,查找出该同学的成绩。
提示1:可以定义两个int型数组,其中一个n存放学号,另一个s存放成绩,可以保证两个数组中,元素下标相同,对应的是同一位同学。例如n[18]值为3123,s[18]为98,说明学号为3123的同学成绩为98。
提示2:因为数据无序,运用顺序查找算法,在n数组中依据学号进行查找,在s数组中对应下标的值则为其成绩。例如,通过在n中的查找,得出学号为3123的同学的下标为18,则其成绩为s[18]。
#include<stdio.h>
#include<stdlib.h>
int readData(int [], int []);
int search(int [], int , int);
int main()
{
int num[200], score[200]; //分别保存学号和成绩
int count; //代表学生人数
int index; //代表查找到的学生的下标
int key;
count = readData(num, score); //将成绩数据从文件中读到数组中
printf("请输入要查找的学生学号:");
scanf("%d",&key);
index = search(num, count, key); //在count个学生中查找学号为key的学生对应的下标
if(index<0) //输入的学号不存在时,index的值要求返回-1
printf("不存在学号为%d的同学\n",key);
else
printf("学号为%d的同学的成绩是:%d\n", key, score[index]);
return 0;
}
int readData(int a[], int b[]) //读取文件数据分别存入两个数组
{
int i=0;
FILE *fp;
if((fp=fopen("score1.txt","r"))==NULL) //只读打开
{
printf("Can not open file!\n");
exit(1);
}
while(!feof(fp)) //读取文件数据
{
fscanf(fp,"%d %d",&a[i],&b[i]);
i++;
}
fclose(fp);
return i;
}
int search(int a[], int n, int x) //查询a[n]中元素x,返回下标
{
int i;
for(i=0;i<n;i++)
{
if(a[i]==x)
return i;
}
if(i>=n)
return -1;
return 0;
}
执行结果
(2)在实际工程中,为了让频繁执行的查询更快一些,常要求对数据进行排序,再进行查询。请改造程序:①在调用readData(num, score);读入数据后,立即调用自定义函数sort对两个数组进行排序(注意在排序需要交换时,应该同时交换两个数组中对应的值,以保证同一下标,对应的是同一个学生的学号和成绩);②这样,search函数可以实现为二分查找了;③改造main函数,支持多次的查找。
#include<stdio.h>
#include<stdlib.h>
int readData(int [], int []);
void sort(int a[], int n, int b[]);
int search(int [], int, int);
int main()
{
int num[200], score[200]; //分别保存学号和成绩
int count; //代表学生人数
int index; //代表查找到的学生的下标
int key;
int go_on; //继续查找标志
count = readData(num, score); //将成绩数据从文件中读到数组中
do
{
printf("\n请输入要查找的学生学号:");
scanf("%d",&key);
index = search(num, count, key); //在count个学生中查找学号为key的学生对应的下标
if(index<0) //输入的学号不存在时,index的值要求返回-1
printf("不存在学号为%d的同学\n",key);
else
printf("学号为%d的同学的成绩是:%d\n", key, score[index]);
printf("\n输入1继续,输入其他值退出...");
scanf("%d",&go_on);
}
while(go_on==1); //输入1继续
return 0;
}
int readData(int a[], int b[]) //读取文件数据分别存入两个数组
{
int i=0;
FILE *fp;
if((fp=fopen("score1.txt","r"))==NULL) //只读打开
{
printf("Can not open file!\n");
exit(1);
}
while(!feof(fp)) //读取文件数据
{
fscanf(fp,"%d %d",&a[i],&b[i]);
i++;
}
fclose(fp);
sort(a,i,b); //同时对数组a[i]和b[i]排序,此处i变量相当于n
return i;
}
void sort(int a[], int n, int b[]) //对a[n]和b[n]同时排序,其中a[n]和b[n]为一一对应关系
{
int j,k,t;
for(j=0; j<n-1; j++)
for(k=0; k<n-1-j; k++)
if(a[k]>a[k+1])
{
t=a[k];
a[k]=a[k+1];
a[k+1]=t;
t=b[k];
b[k]=b[k+1];
b[k+1]=t;
}
}
int search(int a[], int n, int x) //查询a[n]中元素x,返回下标
{
int i;
for(i=0; i<n; i++)
{
if(a[i]==x)
return i;
}
if(i>=n)
return -1;
return 0;
}