【实验目的】
实现动态数组的创建、元素插入、元素删除、数组复制、唯一化、排序(归并排序(自下而上)、选择排序)。
【实验内容】
- 实现一个元素类型为char的动态数组,动态数组的初始容量假设为3。
- 实现动态数组的创建与删除、元素插入、元素删除、动态素组的唯一化。
- 给出序列“CDACDDCECBAABCDCEBCB”的唯一化(Deduplication)结果。
- 可以基于读入某一文件中的字符串。(如:读取Test.txt文件)
- 实现归并排序。(自下而上归并排序)
- 实现选择排序。
- 实现不同元素出现次数的统计。
【实验要求】
- 将上述序列存入动态数组,给出最终动态数组的容量和规模。(请读者自行调整输出)
- 给出在存入上述序列的过程中动态数组调用扩容函数的次数。
- 计算并输出上述序列的唯一化序列。
- 对计算所得的归一化序列,选择排序。
- 对于外部文件中的大量字符排序(归并排序)。(如:对基因的排序)
(下面附上代码)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define inti_len 3 /*初始化数组长度(初始化长度为3)*/
#define dn_lim 0.25 /*下限百分比(若使用的数组长度小于总可用长度的25%,则总可用长度缩小为原来的1/2)*/
#define Default -1 /*插入函数、删除函数 中的参数;表示末尾*/
char* Create_arr (int len);
int Copy_arr (char* From_store,int len,int total_store_len,char** To_store);
int Insert_element (char** store,int* len_p,int total_store_len,char ch,int position);
int Del_element (char** store,int* len_p,int total_store_len,int position);
int Sort_arr (char* store,int now_store_len);
int sort_2arrs(char* store_haed,int len1,char* store_tail,int len2);
int merge_sort(char* store,int now_store_len);
int Unique_arr (char* store,int len,int total_store_len,char** store_unique);
int Frequency_conter (char* store,int now_store_len,int total_store_len);
void Free_arr(char* store);
int Expand_time = 0;//动态数组扩张次数
int Shrink_time = 0;//动态数组收缩次数
/*
author:YXP
e-mail:yxp189@protonmail.com
如有问题,欢迎和我联系~
*/
int main(int argc, char *argv[])
{
Expand_time = 0;
Shrink_time = 0;
clock_t start, finish;//用于计时
int total_store_len = inti_len,now_store_len = 0;//总的可用储存空间,当前使用的长度
int new_len;
char *STORE = "CDACDDCECBAABCDCECB";//待处理字符串
char* store = Create_arr (inti_len);
int i;
/***** 动态读入元素 *****/
printf ("/***** 动态读入元素 *****/\n");
while (STORE[i]!='\0'){
total_store_len = Insert_element (&store,&now_store_len,total_store_len,STORE[i],Default);
/*每次插入一个元素;Insert_element函数详解,见插入操作*/
i++;
}
for (i=0;i<now_store_len;i++){
printf (">>%c",store[i]);
}
printf ("\n");
/****** 唯一化操作 ******/
printf ("/****** 唯一化操作 ******/\n");
char* store_unique;
int uni_len = Unique_arr (store,now_store_len,total_store_len,&store_unique);
/*Unique_arr (数组*,现在使用的长度,可用空间总长,用于储存归一化结果的数组**);*/
for (i=0;i<uni_len;i++){
printf (">>%c",store_unique[i]);
}
printf ("\n");
/******* 排序操作 ******///(选择排序)
printf ("/******* 选择排序 *******/\n");
Sort_arr (store_unique,uni_len);
for (i=0;i<uni_len;i++){
printf (">>%c",store_unique[i]);
}
printf ("\n");
/******* 插入操作 ******/
printf ("/******* 插入操作 ******/\n");
total_store_len = Insert_element (&store,&now_store_len,total_store_len,'$',Default);
/*Insert_element (数组**,现在使用的长度*,可用空间总长,待插入的字符,插入位置(Default表示末尾));*/
for (i=0;i<now_store_len;i++){
printf (">>%c",store[i]);
}
printf ("\n");
/******* 删除操作 ******/
printf ("/******* 删除操作 ******/\n");
total_store_len = Del_element (&store,&now_store_len,total_store_len,0);//删除位置为0的元素
/*Del_element (数组**,现在使用的长度*,可用空间总长,待插入的字符,删除位置(Default表示末尾));*/
for (i=0;i<now_store_len;i++){
printf (">>%c",store[i]);
}
printf ("\n");
/******* 复制操作 ******/
printf ("/******* 复制操作 ******/\n");
char* Copy_store;
int new_total_store_len = Copy_arr (store,now_store_len,total_store_len,&Copy_store);
/*Del_element (数组*,现在使用的长度*,可用空间总长,拷贝到的数组*);*/
for (i=0;i<new_total_store_len;i++){
printf (">>%c",Copy_store[i]);
}
printf ("\n");
/*** 数组当前操作次数 ***/
printf (">>自动扩容%d次\t自动收缩%d次\n\n",Expand_time,Shrink_time);
/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
/*****************************************************/
/******* 对于文件处理+排序操作 ******///(选择/归并排序+计时)
Expand_time = 0;
Shrink_time = 0;
char ch;
char* r_filename = "Test.txt";
char* w_filename = "result.txt";
FILE* fp_c,*fp_w,*fp_r =fopen(r_filename, "r");
/***** 动态读入元素 *****/
printf (">>动态读入元素\n");
start = clock();
while ((ch = fgetc(fp_r)) != EOF){
total_store_len = Insert_element (&store,&now_store_len,total_store_len,ch,Default);
/*每次插入一个元素;Insert_element函数详解,见插入操作*/
i++;
}
finish = clock();
printf (">>读入扩容用时%lf\n",(double)(finish-start)/CLK_TCK);
printf (">>自动扩容%d次\t自动收缩%d次\n\n",Expand_time,Shrink_time);
fclose(fp_r);
printf ("\n");
fp_w = fopen(w_filename, "w");
/******* 选择/归并排序 *******/
printf (">>开始排序\n");
start = clock();
//Sort_arr (store,now_store_len);//选择排序
merge_sort (store,now_store_len);//归并排序
finish = clock();
printf (">>排序用时%lf\n",(double)(finish-start)/CLK_TCK);
for (i=0;i<now_store_len;i++){
fprintf (fp_w,"%c",store[i]);
}
printf (">>排序完成!见文件result.txt!\n");
fclose(fp_w);
/*****************************************************/
/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
/*****元素出现次数统计*****/
Frequency_conter (store,now_store_len,total_store_len);
return 0;
}
char* Create_arr (int len)/*创建一个指定大小的数组*/
{/*Create_arr (数组的长度)
返回值 = 申请所得空间的地址*/
char* store;
store = (char*)malloc(sizeof(char)*len);
return store;
}
void Free_arr(char* store)/*用于创建一个指定大小的数组*/
{/*Free_arr(数组*)*/
free(store);
}
int Copy_arr (char* From_store,int len,int total_store_len,char** To_store)/*用于数组复制*/
{/*Copy_arr (被拷贝数组*,被复制数组长度,可用空间总长n,拷贝所得数组**)
返回值=拷贝所得数组大小;*/
int new_total_store_len, i;
if (len<total_store_len*0.25){
new_total_store_len = (int)(len/2);
*To_store = (char*)malloc(sizeof(char)*(new_total_store_len));
for (i=0;i<len;i++){
(*To_store)[i]=From_store[i];
}
Shrink_time++;
}else{
if ((len+1)>total_store_len){
new_total_store_len = (len*2);
*To_store = (char*)malloc(sizeof(char)*(new_total_store_len));
for (i=0;i<len;i++){
(*To_store)[i]=From_store[i];
}
Expand_time++;
}else{
new_total_store_len = len;
*To_store = (char*)malloc(sizeof(char)*len);
for (i=0;i<len;i++){
(*To_store)[i]=From_store[i];
}
}
}
return new_total_store_len;
}
int Insert_element (char** store,int* len_p,int total_store_len,char ch,int position)/*用于在指定位置,插入指定元素*/
{/* Insert_element (数组**,现在使用的长度*,可用空间总长,待插入的字符,插入位置(Default表示末尾));
返回当前 最大存储空间
注意:position start from 0;
if position = Default,则指末尾;*/
if ((*len_p+1)>total_store_len){
char* temp_store;
total_store_len = Copy_arr (*store,*len_p,total_store_len,&temp_store);
Free_arr(*store);
*store = temp_store;
if (position == Default){
(*store)[*len_p] = ch;
(*len_p)++;
}else{
int i;
for (i = (*len_p)-1;i>=position;i--){
(*store)[i+1] = (*store)[i];
}
(*store)[position] = ch;
(*len_p)++;
}
}else{
if (position == Default){
(*store)[*len_p] = ch;
(*len_p)++;
}else{
int i;
for (i = (*len_p)-1;i>=position;i--){
(*store)[i+1] = (*store)[i];
}
(*store)[position] = ch;
(*len_p)++;
}
}
return total_store_len;
}
int Del_element (char** store,int* len_p,int total_store_len,int position)/*用于删除指定位置元素*/
{/* Del_element (数组**,现在使用的长度*,可用空间总长,待插入的字符,删除位置(Default表示末尾));
返回当前 最大存储空间
注意:position start from 0;
if position = Default,则指末尾;*/
int new_total_store_len;
if ((*len_p-1)<(total_store_len*dn_lim)){
char* temp_store;
new_total_store_len = Copy_arr (*store,*len_p,total_store_len,&temp_store);
Free_arr(*store);
*store = temp_store;
if (position == Default){
(*len_p)--;
}else{
int i;
for (i = position;i<(*len_p);i++){
(*store)[i] = (*store)[i+1];
}
(*len_p)--;
}
}else{
new_total_store_len = total_store_len;
if (position == Default){
(*len_p)--;
}else{
int i;
for (i = position;i<((*len_p)-1);i++){
(*store)[i] = (*store)[i+1];
}
(*len_p)--;
}
}
return new_total_store_len;
}
int Unique_arr (char* store,int len,int total_store_len,char** store_unique)
{/*Unique_arr (数组*,现在使用的长度,可用空间总长,用于储存归一化结果的数组**);
返回值 = 归一化所得数组的长度*/
int i,j,new_len = 0,flag;//flag:0未重复 1重复
*store_unique = (char*)malloc(len*sizeof(char));
for (i=0;i<len;i++){
for (j=0,flag=0;j<new_len;j++){
if (store[i] == (*store_unique)[j]){
flag = 1;
goto AAA;
}
}
AAA:;
if (flag == 0){
(*store_unique) [new_len] = store[i];
new_len ++ ;
}
}
char* temp_store;
total_store_len = Copy_arr (*store_unique,new_len,total_store_len,&temp_store);
Free_arr(*store_unique);
*store_unique = temp_store;
return new_len;
}
int Sort_arr (char* store,int now_store_len)
{
int i,j,min_e;
char min ,temp = '\0';
for (i=0;i<now_store_len;i++){
min = store[i];
for (j=i;j<now_store_len;j++){
if (store[j]<=min){
min_e = j;
min = store[j];
}
}
temp = store[min_e];
store[min_e] = store[i];
store[i] = temp;
}
return 0;
}
int merge_sort(char* store,int now_store_len)//归并排序
{
int i, step = 1, sec_step = 0,thr_step = 0;
for (;((step*3/2)<=now_store_len)||(step==1 );){
for (i=0;i<now_store_len;){
if (((i+2*step)<=now_store_len)&&((i+4*step)<now_store_len)){//小于两步
sort_2arrs(&(store[i]),step,&(store[i+step]),step);
i=i + 2*step;
}else{
if ((i+4*step)>=now_store_len){
sec_step = now_store_len-i-2*step;
thr_step = now_store_len-i-step;
// Sort_arr (&(store[i+step]),sec_step);
sort_2arrs(&(store[i+step]),step,&(store[i+2*step]),sec_step);
sort_2arrs(&(store[i]),step,&(store[i+step]),thr_step);
i=now_store_len;
}
}
}
step=step*2;
}
return 0;
}
int sort_2arrs(char* store_haed,int len1,char* store_tail,int len2)//两有序数组间排序
{
int temp_now_store_len = len1+len2;
char* temp_store = Create_arr (temp_now_store_len);
char temp;
int i;
int k = 0,k1 = 0,k2 = 0;
while ((k1!=(len1))||(k2!=(len2))){
if (k1==len1){
while ((k<temp_now_store_len)&&(k2 <len2)){
temp_store[k++] = store_tail[k2++];
}
}
if (k2==len2){
while ((k<temp_now_store_len)&&(k1 <len1)){
temp_store[k++] = store_haed[k1++];
}
}
while((store_haed[k1]<=store_tail[k2])&&(k1 <len1)){
temp_store[k++] = store_haed[k1++];
}
while((store_haed[k1]>store_tail[k2])&&(k2 <len2)){
temp_store[k++] = store_tail[k2++];
}
}
for (i=0;i<len1;i++){
store_haed[i] = temp_store[i];
}
for (i=0;i<len2;i++){
store_tail[i] = temp_store[len1+i];
}
free (temp_store);
return 0;
}
int Frequency_conter (char* store,int now_store_len,int total_store_len)
{
char* store_unique;
int new_len = Unique_arr (store,now_store_len,total_store_len,&store_unique);
int *temp_counter= (int*)malloc(new_len*sizeof(int));
int i,k;
for (i=0;i<new_len;i++){
temp_counter[i]=0;
}
for (i=0,k=0;i<now_store_len;i++){
if (store[i]==store_unique[k]){
temp_counter[k]++;
}else{
k++;
temp_counter[k]++;
}
}
for (i=0;i<new_len;i++){
printf (">>%c = %d\n",store_unique[i],temp_counter[i]);
}
return 0;
}