排序过程主要是对记录的排序码进行比较和记录的移动过程,因此排序的时间复杂性以算法执行中的数据的比较次数和数据移动次数来衡量。
内部排序通过过程中所依据的原则不同可以分为三类:
1.插入排序
2.归并排序
3.快速排序
一、插入排序
直接插入排序
#include <stdio.h>
void insertSort(int a[],int n)
{
for(int i = 1;i < n;i++)
{
int j = i-1;
int index = a[i];//用一个数来记住这个将要移动的a[i]
while(j >= 0 && index < a[j])//如果这个将要移动的数一直比前面的小,那么将不断移动它
{
a[j+1] = a[j];//把比它大的数字不断向后面移动
j--;
}
a[j+1] = index;//最后找到了这个数字应该在的位置
}
}
int main() {
int a[10] = {5,3,1,2,10,7,2,0,19,4};
insertSort(a,10);
for(int i = 0;i < 10;i++)
{
printf("%d ",a[i]);
}
return 0;
}
插入排序的效率分析如下
二、归并排序
思考:如何用分治的思想解决这个问题?
1.分解:将n个元素分成各含n/2个元素的子序列
2.解决:递归地用合并排序法对两个子序列排序
3.合并:合并两个已经排好的序列
归并排序的基本思想为:将待排序列元素分成大小相致相同的两个子集合,分别对两个子集合进行排序,最终将排好的子集合合并成为所要求的排好序的集合。
#include <iostream>
#include<fstream>
#include<string>
using namespace std;
int n = 0;//全局变量n,表示从文件中读入数组a的长度
int charToInt(string str);//将读取到的字符转为对应的数字
int* fileToArray(FILE * file);//从输入文件中读取出数组大小和数组
void mergeSort(int a[],int n);//对数组a进行排序
void mergePass(int a[],int b[],int length);//通过对不同情况的分析对merge调用来对给出的数组规定步长进行排序
void merge(int a[],int b[],int left,int middle,int right);//将给出的两组数合并到一组数里面存在数组b中
/*将给出的两组数合并到一组数里面存在数组b中*/
void merge(int a[],int b[],int left,int middle,int right)
{//a表示给出的数组,b表示将两组数排好了归并到数组b中,left表示第一个数组起始,middle第一个数组结束,left第二个数组结束
int i = left;
int j = middle + 1;//j表示需要合并的第二个数组的起始位置
int k = left;//用来标记数组b
while(i <= middle && j <= right)
{
if(a[i] < a[j])
{
b[k++] = a[i++];
}
else if(a[i] > a[j])
{
b[k++] = a[j++];
}
else
{
b[k++] = a[i++];
b[k++] = a[j++];
}
}
if(i > middle && j <=right)
{
while(j <= right)
{
b[k++] = a[j++];
}
}
else if(i <= middle && j >right)
{
while(i <= middle)
{
b[k++] = a[i++];
}
}
}
/*通过对不同情况的分析 对merge进行调用,来对给出的数组进行规定步长的排序*/
void mergePass(int a[],int b[],int length)
{//a为给出数组,b为归并后的数组,length为给出的步长
int temp = n % (2 * length);
if(temp == 0)
{
for(int i = 0;i < n;i += 2*length)
{
merge(a,b,i,i + length -1,i + 2*length - 1);
}
}
else if(temp <= length)
{
int i = 0;
for(;i < n - temp;i += 2*length)
{
merge(a,b,i,i + length -1,i + 2*length - 1);
}
int k = n - temp;
while(k < n)
{
b[k] = a[k];
k++;
}
}
else if(temp > length)
{
int i = 0;
for(;i < n - temp;i += 2*length)
{
merge(a,b,i,i + length -1,i + 2*length - 1);
}
merge(a,b,i,i + length - 1,n-1);
}
}
/*对a进行排序,通过传入不同的步长,调用mergePass函数*/
void mergeSort(int a[],int n)
{
int *b=new int [n];
int length = 1;
while(length < n)
{//迭代排序,从最小的步长为1开始
mergePass(a,b,length);
length += length;
mergePass(b,a,length);
length += length;
}
}
/*将字符转换为对应数字(非ascii)*/
int charToInt(string str)
{
int len = str.length();
int result = 0;
for(int i = 0;i < len;i++)
{
result = result *10 + (str[i]-'0');
}
return result;
}
/*从文件中获取数组信息*/
int * fileToArray(FILE * file)
{//通过读出以空格为分届的字符串,将字符串转换为数字
string str ="";
char c=fgetc(file);
while(c>='0' and c<='9')
{
str += c;
c = fgetc(file);
}
n = charToInt(str);
int * a = (int *)malloc(n*sizeof(8));
for(int i = 0;i < n;i++)
{
str = "";
c = fgetc(file);
while(c >='0' and c <='9')
{
str += c;
a[i] = charToInt(str);
c = fgetc(file);
}
}
return a;
}
int main()
{
int * a;
FILE* fpin;
fpin = fopen("./mergesort.in.txt","r") ;
if(fpin == NULL){
printf("文件读入失败");
}
a = fileToArray(fpin);
mergeSort(a,n);
ofstream os;//创建一个文件输出流对象
os.open("./mergesort.out.txt");//将对象与文件关联
for(int i = 0;i < n;i++)
{
string str;
str = to_string(a[i]);
os<<str; //将输入的内容放入txt文件中
os<<' ';
}
os.close();
fclose(fpin);
return 0;
}