#include #include#include#include"Sort.h"#include
/*辅助交换函数*/
int Swap(int* str, int pos1, intpos2)
{if (str ==NULL)
{return -1;
}if (pos1 < 0 || pos2 < 0)
{return -2;
}/*交换数组pos1的值和pos2的值*/
int temp =str[pos1];
str[pos1]=str[pos2];
str[pos2]=temp;return 0;
}/*打印数组元素*/
void PrintArraryElement(int* str, intlength)
{
assert(str!=NULL);
printf("\t\t\t");for (int i = 0; i < length; i++)
{
printf("%d\t", str[i]);
}
printf("\n");
}/*选择排序*/
int SelectSort(int* str, intlength)
{/*算法思想
第一次:i=0(j=1,此时比较str[0],str[1]。如果str[1]比str[0]还小的话,进行交换,此时str[0]是前2个最小值了。接着j=2的时候,也就是第3个元素的时候,在进行比较str[0],str[2]。如果str[2]比str[0]小的话,进行交换。此时str[0]就是前3个最小值了。类推。i=0;执行完的时候第一个元素str[0]一定是所有元素中最小的那一个。这样第一个元素就是有序的。
第二次:i=1执行过程和i=0类似,只是每次都是和str[1]进行比较了。str[0]是不参与比较的。所以i=1执行完后,str[1]一定是str[1]到str[length-1] 元素的最小值。这样前2个元素是有序的。
第三次:i=2。这样前3个元素是有序的。
第N次:i=n-1。 这样前N个元素是有序的。也就是所有元素都是有序的啦。
总结:每次都是和固定的位置那个元素进行比较。*/assert(str!=NULL);for (int i = 0; i < length; i++)
{for (int j = i + 1; j < length; j++)
{if (str[i] >str[j])
{
Swap(str, i, j);
}
}
}return 0;
}/*冒泡排序*/
int BubbleSort(int* str, intlength)
{/*算法思想
第一次:i=0(j=0,此时比较str[0],str[1]。如果str[1]比str[0]还小的话,进行交换,此时str[0]是前2个最小值了 str[1]是前2个最大值。接着j=1的时候,在进行比较str[1],str[2]。如果str[2]比str[1]小的话,进行交换。此时str[2]就是前3个最大值了。类推。i=0;执行完的时候最后一个元素str[length-1]一定是所有元素中最大的那一个。这样最后一个元素就是有序的。
第二次:i=1执行过程和i=0类似,每次相邻元素进行比较。所以i=1执行完后,倒数第二个元素str[length-2]一定是str[0]到str[length-2] 元素的最小值。这样后2个元素是有序的。
第三次:i=2。这样后3个元素是有序的。
第N次:i=n-1。 这样后N个元素是有序的。也就是所有元素都是有序的啦。
总结:每次都是相邻的元素进行比较,可以定义一个flag标示变量前面的结果是否有序进行优化。*/assert(str!=NULL);for (int i = 0; i < length; i++)
{for (int j = 0; j < length - 1; j++)
{if (str[j] > str[j + 1])
{
Swap(str, j, j+ 1);
}
}
}return 0;
}/*插入排序*/
int InsertSort(int* str, intlength)
{/*算法思想
这里举例个数据 1 , 2 ,4 , 5 , 3
核心:就是取出来一个元素,然后和前面的有序序列进行比较,找到合适的位置。插进去,这个位置的后面的需要后移。
对于上面的这个数组一共5个元素,前4个是有序的。那么怎么讲第5个元素(3)插入到指定位置呢。
1.取出来: 先用一个变量pos 保存3这个元素的位置下标(pos =4),用一个value保存这个元素的值(3 )。
2.进行比较: 前面的4个元素(1,2,4,5)是有序的。先将 3和有序序列的最后一个元素(5)进行比较,3是小于5的,那么就将5这个元素放到原来3的为位置上去,这样5的这个位置就空出来了(也就是取出来了 pos =3)在和4进行比较。3小于4的。那么4这个元素后移下。这样pos=2的位置就空出来了。
3在和2进行比较,3是大于2的,for循环结束 把value(3) 赋值到pos位置上去,也就是str[pos] =value,级str[2] =3;
3.这样结果就是有效的了。
当然开始的时候前面几个不是有序的,至少第一个元素是有序的。那么就从第二个元素开始进行插入。也就是i=1开始,i=1结束的时候前面2个元素是有序
i=2,结束的时候前面3个元素是有序的。i=length -1,结束的时候前面length 个元素都是有序的。也就是整个数组是有序的。*/assert(str!=NULL);for (int i = 1; i < length; i++)
{int pos =i;int value =str[i];for (int j = i-1; j >=0 && str[j] >value; j--)
{
str[j+ 1] =str[j];
pos=j;
}
str[pos]=value;
}return 0;
}/*希尔排序*/
int ShellSort(int* str, intlength)
{/*算法思想:
核心代码和插入排序一样。加入了分组处理,gap=gap/3+1 这样分组是效率最高的。*/assert(str!=NULL);int gap =length;do{
gap= gap / 3 + 1;for (int i = gap; i < length; i+=gap)
{int pos =i;int value =str[i];for (int j = i - gap; j >= 0 && str[j] >value; j-=gap)
{
str[j+ gap] =str[j];
pos=j;
}
str[pos]=value;
}
}while (gap > 1);return 0;
}/*快速排序*/
/*******************************************************************************/
int Partition(int* str, int low, inthigh)
{/*函数功能:就是分隔str的low元素到high的元素(一共high-low+1个)比第一个元素(temp=str[low])大的都放到右边,比temp小的都放到左边。
算法思想:
这里给一个简单的数组来解释这个函数的功能
str 的数组元素(7个 low =0 high =6) 8,7,2,4,8,9,2
1.取temp =str[low]=8;
2;low就是第一个元素的下标,high就是最后一个元素的下标。第一次判断str[high] >= temp 为假,交换8和2 此时low =0 high =6数组变成了2,7,2,4,8,9,8 接着判断str[low]<=temp(2<8)为真,low++,此时low =1,high =6 ,接着判断str[low]<=temp(7<8)为真,low++,此时low=2,high=6,接着判断str[low]<=temp(2<8)为真low++,此时low=3,high=6 接着判断str[low]<=temp(4<8)为真low++,此时low=4,high=6,接着判断str[low]<=temp(8<=8)为真low++,low=5,high=6,接着判断str[low]<=temp(9<=8)为假,交换9和8,此时low=5,high=6 数组变成了2,7,2,4,8,8,9,接着进行判断str[high]>=temp(9>=8)为真,high--此时low=5,high=5 ,交换low和high位置元素,其实是一样的。最终返回一个low也就是5,也就是初始的第一个元素现在在这个数组的位置下标啦。最终得到的数组就是2,7,2,4,8,8,9.*/assert(str!=NULL);int temp =str[low];while (low
{while (low =temp)
{
high--;
}
Swap(str, low, high);while (low
{
low++;
}
Swap(str, low, high);
}returnlow;
}int QSort(int* str, int low, inthigh)
{/*算法思想:
int par =Partition(str,low,high)执行后返回一个数组下标值par,str数组中数组下标小于par的元素都是小于str[par]的。数组下标大于par的元素都是大于str[par]的。这个时候str[par]就是不会在改变了。
QSort(str, low, par - 1);就是给low 到par-1的那些元素进行分割,每次都会确定一个str[par]的值不会再去改变的。
剩下的就是递归调用完成最终的排序计算。*/assert(str!=NULL);if (low
{int par =Partition(str, low, high);
QSort(str, low, par- 1);
QSort(str, par+ 1, high);
}return 0;
}int QuickSort(int* str, intlength)
{
assert(str!=NULL);return QSort(str, 0, length - 1);
}/*归并排序*/
/*******************************************************************************/
void Merge(int* src, int* dst, int low, int mid, inthigh)
{/*归并排序算法思想:
src1 low到mid是有序的,mid到high是有序的。
这个函数就是将2个各自有序的数组合成一个数组
一个数组是1 ,4, 5 ,7 一个数组是2,3 ,6,8,9 10
第一次判断src[i]
第二次判断src[i]
最终会有一个数组剩下元素,另一个数组没有元素的。
将那个数组的元素copy到结果数组中去。*/assert(src!=NULL);
assert(dst!=NULL);int i =low;int j = mid + 1;int k =low;while (i<=mid && j<=high)
{/*每次插入两个数组的头部最小值到目标数组中,保证了目标数组是有序的*/
if (src[i]
{
dst[k++] = src[i++];
}else{
dst[k++] = src[j++];
}
}/*将剩下的那部分copy到目标数组中去*/
while (i<=mid)
{
dst[k++] = src[i++];
}while (j<=high)
{
dst[k++] = src[j++];
}
}int MSort(int* src, int* dst, int low, int high, intmax)
{
assert(src!=NULL);
assert(dst!=NULL);if (low ==high)
{/*只有一个元素的时候直接给目标数组赋值了。不用在递归啦*/dst[low]=src[low];return 0;
}else{int mid = (low + high) / 2;int *space = (int*)malloc(sizeof(int)*max);if (space ==NULL)
{return -1;
}//递归调用进行分割直到只有一个元素递归结束
MSort(src, space, low, mid, max);
MSort(src, space, mid+ 1, high, max);//对递归的数据进行合并
Merge(space, dst, low, mid, high);if (space !=NULL)
{free(space);
}return 0;
}return 0;
}int MergeSort(int* str,intlength)
{
assert(str!=NULL);return MSort(str, str, 0, length - 1, length);
}