0
点赞
收藏
分享

微信扫一扫

vue3-element-admin的组件el-time-picker设置只能选择上午或下午

排序类型小结

💦 插入排序

直接插入排序

🔑 核心思想 🔑
请添加图片描述

🐳 把待排序的记录按关键码的大小逐个插入到一个已经排好的序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列

❗ 过程:❕

当插入第 i(i>=1) 个元素时,前面的 array[0], array[1], … , array[i-1] 已经排好序,此时用 array[i] 的排序码与 array[i-1], array[i-2],… 的排序码顺序进行比较,找到插入位置即将 array[i] 插入,原来位置上的元素顺序后移

❗ 直接插入排序的特性总结:❕

1️⃣ 元素集合越接近有序,直接插入排序算法的时间效率越高

2️⃣ 时间复杂度:O(N^2)

3️⃣ 空间复杂度:O(1),它是一种稳定的排序算法

4️⃣ 稳定性:稳定
  
🐾代码实现:

void InsertSort(int* a, int n)
{
	//注意这里的n-1
	for (int i = 0; i < n-1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				//后移数组
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

希尔排序

希尔排序 (缩小增量排序)

🔑 核心思想 🔑

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成若干个组,所有距离为 gap 的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达gap == 1 时,所有记录在统一组内排好序。

在这里插入图片描述

🤖希尔排序的时间复杂度并不好计算,因为 gap 的取值方法很多,导致很难去计算,因此在好些数中给出的希尔排序的时间复杂度都不固定,官方给出的时间复杂度是 O(N1.3)

以下是其粗略的计算方法,可见非常复杂

在这里插入图片描述
🐾代码实现

//希尔排序
void ShellSort(int* a, int n)
{
	int gap = n;
	//gap>1时是预排,目的是让他接近有序
	//gap==1是直接插入排序,目的是让他有序
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		//多组并排
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
					break;
			}
			a[end + gap] = tmp;
		}
	}
}

❗ 希尔排序特性总结 ❕

1️⃣ 希尔排序是对直接插入排序的优化

2️⃣ 当 gap > 1 时都是预排序,目的是让数组更接近于有序。当 gap == 1 时,其实就是直接插入排序,且数组已经接近有序的了。整体而言,可以达到优化的效果,我们实现后可以进行性能测试的对比

3️⃣ 希尔排序的时间复杂度并不好计算,因为 gap 的取值方法很多,导致很难去计算,因此在好些数中给出的希尔排序的时间复杂度都不固定,官方给出的时间复杂度是 O(N1.3)

4️⃣ 稳定性:不稳定

💦 选择排序

直接选择排序

🔑 核心思想 🔑

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

❗ 过程:❕

1️⃣ 在元素集合 array[i] - array[n-1] 中选择关键码最大 (小) 的数据元素

2️⃣ 若它不是这组元素中的最后一个(或第一个)元素,则将它与这组元素中的最后一个(或第一个)元素交换

3️⃣ 在剩余的 array[i] - array[n-2] (array[i+1]–array[n-1]) 集合中,重复上述步骤,直到集合剩余 1 个元素

❗ 直接选择排序的特性总结:❕

1️⃣ 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用

2️⃣ 时间复杂度:O(N^2) - 最好 / 最坏都是如此,当数据极其无序时,比冒泡排序还要拉跨

3️⃣ 空间复杂度:O(1)

4️⃣ 稳定性:不稳定

❗ 动图演示:❕
请添加图片描述
🐾代码实现


//与上述动图一样的代码
void Swap(int* px, int* py)
{
	int temp = *px;
	*px = *py;
	*py = temp;
}
void SelectSort(int* a, int n)
{
	int i = 0;
	int begin = 0;
	while (begin < n)
	{
		int mini = begin;
		//选最小
		for (i = begin; i < n; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
		}
		//交换
		Swap(&a[begin], &a[mini]);
		//迭代
		begin++;
	}
}

//优化版本,最大值最小值同时找
void SelectSort(int* a, int n)
{
	int begin = 0, end = n - 1;
	while (begin < end)
	{
	  //一趟排序,将最大数最小数的下标都初始化成begin
		int mini = begin, maxi = begin;
		//遍历数组,找到最大数和最小数的下标
		for (int i = begin + 1; i <= end; ++i)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}

		Swap(&a[begin], &a[mini]);
		//如果没有这个if判断,最大值的下标指向会随着begin的mini的交换使得max的值丢失
		//当maxi==begin时,maxi指向min,下一次交换就会出问题!!!
		if (maxi == begin)
		{
			maxi = mini;
		}
		Swap(&a[end], &a[maxi]);
        //迭代
		++begin;
		--end;
	}
}

堆排序

🔑 核心思想 🔑

堆排序 (Heapsort) 是指利用堆积树 (堆) 这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。

❗ 堆排序的特性总结:❕

1 堆排序使用堆来选数,效率就高了很多。

2. 时间复杂度:O(N*logN)

3.空间复杂度:O(1)

4.稳定性:不稳定

void Swap(int* px, int* py)
{
	int temp = *px;
	*px = *py;
	*py = temp;
}
//向上调整算法
void AdjustUp(int*a,int child)
{
  int parent=(child-1)/2;
  while(child > 0)
  {
       //这里的符号决定调整为大堆还是小堆,这里以大堆为例
     if(a[child]>a[parent])
     {
      Swap(&a[child],&a[parent]);
      child=parent;
      parent=(child-1)/2;
     }
     else
     {
       break;
     }
     
  }
}
//向下调整算法
void AdjustDown(int* a, int size, int parent)
{

	int child = parent * 2 + 1;
	while (child < size)
	{
	//假设左孩子小,如果假设错了,更新一下
	//这样操作后,child指向的就是两个孩子中较小的那一个
		if (a[child+1] < a[child] && child + 1 < size)
		{  
			child++;
		}
		//如果孩子大,就交换(决定了大堆还是小堆)
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			//交换后,更新下标
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
//排升序
void HeapSort(int* a, int n)
{
  //建大堆
  for(int i=0;i<n;i++)
  {
    AdjustUp(a,i); 
  }
  int end=n-1;
  while(end>0)
  {
    //交换后最大的数就排好了
     Swap(&a[0],&a[end]);
     //将前面的数再调整,选出次小的数
     AdjustDown(a,end,0);
     end--;
  }
}

方法二:用向下调整算法建堆

void Swap(int* px, int* py)
{
	int temp = *px;
	*px = *py;
	*py = temp;
}

//排升序
void HeapSort(int* a, int n)
{
	//建大堆
	int i = 0;
	//n-1就是最后一个元素下标,再-1,除以二就是其父节点,也就是倒数第一个非叶子节点
	//从这开始从下往上向下建堆
	for (i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}
	int end = n - 1;
	//交换并删除堆中最后一个元素
	while (end > 0)
	{
	   //首尾交换
		Swap(&a[0], &a[end]);
		//重新建大堆
		AdjustDown(a, end, 0);
		end--;
	}
}

  • 倒着调整叶子节点不需要处理(因为叶子节点没有子节点无法向下比较),从倒数第一个非叶子节点开始,即最后一个节点的父节点开始调整,从下往上向下建堆。

  • 在HeapSort函数中,第一个循环调用了AdjustDown函数,将待排序数组构建成了一个大堆。但是,这个大堆并不是完全有序的,只是满足了大堆的性质,即每个节点的值都大于或等于其左右子节点的值。因此,需要进行第二个while循环,将大堆根中的元素依次取出,交换堆顶元素和数组末尾元素,并重新调整大堆,直到整个数组有序。

  • 第二个while循环中,将堆顶元素与数组末尾元素交换,然后将剩余元素重新调整为大根堆。这样,每次交换后,数组末尾的元素就是当前大根堆中的最大值,而剩余元素仍然满足大根堆的性质。重复以上步骤,直到整个数组有序。

💦 交换排序

冒泡排序

请添加图片描述

// 时间复杂度:O(N^2)
// 最好情况是多少:O(N)
void BubbleSort(int* a, int n)
{
	for (int j = 0; j < n; j++)
	{
	   //定义exchange可以优化冒泡排序,当数据已经有序时,可以提前结束排序
		bool exchange = false;
		for (int i = 1; i < n-j; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				exchange = true;
			}
		}

		if (exchange == false)
			break;
	}

快速排序🐾

🔑 核心思想 🔑

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

❗ 过程:❕

霍尔版本

请添加图片描述

1️⃣ 选出一个关键字 key,一般是头或者尾

2️⃣ 经过一次单趟后,key 放到了正确的位置,key 左边的值比 key 小,key 右边的值比 key 大

3️⃣ 再让 key 的左边区间有序、key 的右边区间有序

//简易版本
QuickSort(int* a,int begin,int end)
{
  	if(begin>=end)
  	return;
  	//注意left的起始位置,如果这里left=begin+1,当数组有序时会出Bug
  	int keyi=begin,left=begin,right=end;
  	while(left<right)
  	{
      //右边找小
      //注意循环条件的控制
      while(left<right&&a[right]>=a[keyi])
      {
        right--;
      } 
      //左边找大
      while(left<right&&a[left]<=a[keyi])
      {
        left++;
      }
      Swap(&a[left],&a[right]);
    }
   Swap(&a[left],&a[keyi]);
   //更新下一次递归时区间边界
   keyi=left;
   //与二叉树的先序遍历有异曲同工之妙
   QuickSort(a,begin,keyi-1);
   QuickSort(a,keyi+1,end);
}
//优化代码
//三数取中函数
int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	// begin end midi三个数选中位数
	if (a[begin] < a[midi])
	{
		if (a[midi] < a[end])
			return midi;
		else if (a[begin] > a[end])
			return begin;
		else
			return end;
	}
	else//a[begin] > a[midi]
	{
		if (a[midi] > a[end])
			return midi;
		else if (a[begin] > a[end])
			return end;
		else
			return begin;
	}
}

void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;

	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);

	int left = begin, right = end;
	int keyi = begin;

	while (left < right)
	{
		// 右边找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}

		// 左边找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}

		Swap(&a[left], &a[right]);
	}

	Swap(&a[left], &a[keyi]);
	keyi = left;

	// [begin, keyi-1] keyi [keyi+1, end]
	QuickSort(a, begin, keyi - 1);
	QuickSort(a, keyi + 1, end);
}
//对小区间处理的插入排序函数
void InsertSort(int* a, int n)
{
	//注意这里的n-1
	for (int i = 0; i < n-1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				//后移数组
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}
//找中位数函数
int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	// begin end midi三个数选中位数
	if (a[begin] < a[midi])
	{
		if (a[midi] < a[end])
			return midi;
		else if (a[begin] > a[end])
			return begin;
		else
			return end;
	}
	else//a[begin] > a[midi]
	{
		if (a[midi] > a[end])
			return midi;
		else if (a[begin] > a[end])
			return end;
		else
			return begin;
	}
}
//快排函数
void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;
		//end-begin+1是数据个数,规定其小于10时采用插入排序
   if(end-begin+1<10)
   //注意这里的递归起始区间位置是a+begin
    InsertSort(a+begin,end-begin+1);
    else
	{
    int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);

	int left = begin, right = end;
	int keyi = begin;

	while (left < right)
	{
		// 右边找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}

		// 左边找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}

		Swap(&a[left], &a[right]);
	}

	Swap(&a[left], &a[keyi]);
	keyi = left;

	// [begin, keyi-1] keyi [keyi+1, end]
	QuickSort(a, begin, keyi - 1);
	QuickSort(a, keyi + 1, end);
    }
}
  • 下图是测试优化小区间后的快排效果,数字代表跑完程序所用的毫秒数,测试方法文末附有,我们对由10万个随机数构成的数组进行排序,为了使得对比更明显,我们在debug(调试版本)下进行对比,debug下,每个函数栈帧添加了许多调试信息,占用的空间更大,小区间优化的效果更加明显。而release(发布版本)对调试信息进行了优化,函数栈帧过多影响不大,多敲的代码可能还会降低排序速度,起到适得其反的效果。

为了方便和后续新的方法对比,我们把霍尔版本的单趟排序抽离出来,定义为PartSort1函数

int PartSort1(int* a, int begin, int end)
{
	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);
	int left = begin, right = end;
	int keyi = begin;

	while (left < right)
	{
		// 右边找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}

		// 左边找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}

		Swap(&a[left], &a[right]);
	}

	Swap(&a[left], &a[keyi]);

	return left;
}
//函数 PartSort1 返回了 left 指针指向的值
//这个值表示基准值在分区后的位置。在快速排序算法中,
//这个值会被用来确定下一次分区的区间范围。
void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;
		//end-begin+1是数据个数,规定其小于10时采用插入排序
   if(end-begin+1<10)
   //注意这里的递归起始区间位置是a+begin
    InsertSort(a+begin,end-begin+1);
    else
	{
    int keyi=PartSort1(a,begin,end);
	QuickSort(a, begin, keyi - 1);
	QuickSort(a, keyi + 1, end);
    }
}

补坑位版本

动图展示💦
请添加图片描述

//补坑位版本
int PartSort2(int* a,int begin,int end)
{
   int midi=GetMidi(a, begin, end);
   Swap(&a[midi],&a[begin]);
   int key=a[begin];
   int hole=begin;
   while(begin<end)
   {
     //右边找小,找到后填到左边坑位
     while(begin<end && key>=a[end])
     {
       end--;
     }  
     a[hole]=a[end];
     hole=end;
     //左边找大,找到后填到右边坑位
     while(begin<end&&key<=a[begin])
     {
      begin++;
     }
     a[hole]=a[begin];
     hole=begin;
   }
   a[hole]=key;
   return hole;
}

前后指针版本

请添加图片描述
第一趟交换后的结果
在这里插入图片描述

int PartSort3(int*a,int begin,int end)
{
  int midi=GetMidi(a,begin,end);
  Swap(&a[begin],&a[midi]);
  int prev=begin;
  int cur=prev+1;
  int key=a[begin];
 while(cur<=end)
 {
   if(key<=a[cur])
   {
    cur++;
   }
   else
   {
     prev++;
     Swap(&a[prev],&a[cur]); 
     cur++;
   }
 }
 Swap(&a[prev],&key);
 return prev;
}

ok了这个测试后也没啥问题
在这里插入图片描述
在这里插入图片描述

int PartSort3(int* a, int begin, int end)
{
	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);
	int keyi = begin;

	int prev = begin;
	int cur = prev + 1;
	while (cur <= end)
	{
	//循环内部其实还可以进一步简化代码
		if (a[cur] < a[keyi] && ++prev != cur)
			Swap(&a[prev], &a[cur]);

		++cur;
	}

	Swap(&a[prev], &a[keyi]);
	keyi = prev;
	return keyi;
}

非递归版本

如果想将快排仅仅利用循环是不现实的,因为递归的子区间左右区间不好控制,这里我们需要借助栈的结构

void QuickSortNonR(int* a, int begin, int end)
{
	ST s;
	STInit(&s);
	//第一次入栈要将整个数组的左右区间进栈
	STPush(&s, end);
	STPush(&s, begin);

	while(!STEmpty(&s))
	{
	  //记录左右区间后出栈
		int left = STTop(&s);
		STPop(&s);
		int right = STTop(&s);
		STPop(&s);
       //利用存好的左右区间进行一趟快排,找到keyi
		int keyi = PartSort3(a, left, right);
		// [left, keyi-1] keyi [keyi+1, right]
		//当子区间合法时,继续入栈
		if (left < keyi - 1)
		{
			STPush(&s, keyi - 1);
			STPush(&s, left);
		}

		if (keyi + 1 < right)
		{
			STPush(&s, right);
			STPush(&s, keyi+1);
		}
	}

	STDestroy(&s);
}

💦 归并排序

动图展示
请添加图片描述

在这里插入图片描述

递归版本

void _MergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin >= end)
		return;

	int mid = (begin + end) / 2;
	// [begin, mid][mid+1, end]
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid+1, end, tmp);

	// [begin, mid][mid+1, end]归并
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	while(begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
   //将tmp数组中的值拷贝回去
	memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}

void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
   
	_MergeSort(a, 0, n - 1, tmp);
	free(tmp);
}

小结

  • 主函数接受两个参数,一个整数数组a和一个整数n,n 表示数组的长度。

  • MergeSort 函数首先为tmp数组开辟待空间。

  • 调用_MergeSort函数进行排序。

  • 释放tmp的空间。

  • 在子函数中,首先计算中间位置mid,并递归地对数组的两部分进行排序。这是分治的思想,将大问题分解成小问题,使用四个指针begin1和begin2、end1和end2,分别指向两个部分的开始位置和结束位置,

  • 然后看三个while循环的比较插入过程,每次分割后两部分分别从头开始比较,把较小的插入tmp数组,某一部分的数全部插入数组后,结束第一个while循环。继续检查哪个数组还有剩余元素,剩下的都是较大的,直接插入tmp数组中。

  • 接下来,我们需要从最小的子序列到最大依次往上进行排序插入,所以这里引用递归的思想完成排序:

  • 在函数_MergeSort中,首先判断begin是否等于end,如果相等,则当前子序列只有一个元素,不需要排序,直接返回。

  • 如果不相等,则计算中间位置mid,然后递归调用_MergeSort函数对左半部分和右半部分进行排序。在排序完成后,将左半部分和右半部分合并成一个有序数组tmp。

  • 每层递归排序后,使用memcpy函数将临时数组tmp中的元素复制回原数组a中。

非递归版本

void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
      //通过gap控制归并的子数组大小实现非递归的归并排序
	int gap = 1;
	while (gap < n)
	{
		printf("gap:%2d->", gap);
		for (size_t i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;

			// 边界的处理
			if (end1 >= n || begin2 >= n)
			{
				break;
			}

			if (end2 >= n)
			{
				end2 = n - 1;
			}

	      //开始归并
			int j = begin1;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}

			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}

			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}

			memcpy(a + i, tmp + i, sizeof(int) * (end2-i+1));
		}

		printf("\n");

		gap *= 2;
	}


	free(tmp);
}

在这里插入图片描述
在这里插入图片描述

💦 性能测试

void TestInsertSort()
{
	int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };
	InsertSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

void TestBubbleSort()
{
	int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };
	BubbleSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

void TestShellSort()
{
	//int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };
	int a[] = { 13, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };
	ShellSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

void TestSelectSort()
{
	//int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };
	int a[] = { 13, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1};

	SelectSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

void TestHeapSort()
{
	//int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };
	int a[] = { 13, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };

	HeapSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

void TestQuickSort()
{
	//int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };
	//int a[] = {6,1,2,7,9,3,4,5,10,8};
	int a[] = { 6,1,2,6,7,9,3,4,6,10,8 };
	PrintArray(a, sizeof(a) / sizeof(int));

	//QuickSort(a, 0, sizeof(a) / sizeof(int)-1);
	QuickSortNonR(a, 0, sizeof(a) / sizeof(int) - 1);

	PrintArray(a, sizeof(a) / sizeof(int));
}

void TestMergeSort()
{
	//int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };
	//int a[] = {6,1,2,7,9,3,4,5,10,8};
	//int a[] = { 6,1,2,6,7,9,3,4,6,10,8 };
	int a[] = { 10,8,7,1,3,9,4,2,9,10,1,1,2,3};
	PrintArray(a, sizeof(a) / sizeof(int));

	MergeSortNonR(a, sizeof(a) / sizeof(int));

	PrintArray(a, sizeof(a) / sizeof(int));
}

void TestCountSort()
{
	int a[] = {1,3,9,1,5,1,2,3,-5,-5,-2 };
	PrintArray(a, sizeof(a) / sizeof(int));

	CountSort(a, sizeof(a) / sizeof(int));

	PrintArray(a, sizeof(a) / sizeof(int));
}

// 测试排序的性能对比
void TestOP()
{
	srand(time(0));
	const int N = 10000000;
	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a2 = (int*)malloc(sizeof(int) * N);
	int* a3 = (int*)malloc(sizeof(int) * N);
	int* a4 = (int*)malloc(sizeof(int) * N);
	int* a5 = (int*)malloc(sizeof(int) * N);
	int* a6 = (int*)malloc(sizeof(int) * N);
	int* a7 = (int*)malloc(sizeof(int) * N);
	int* a8 = (int*)malloc(sizeof(int) * N);

	for (int i = 0; i < N; ++i)
	{
		a1[i] = rand();
		a2[i] = a1[i];
		a3[i] = a1[i];
		a4[i] = a1[i];
		a5[i] = a1[i];
		a6[i] = a1[i];
		a7[i] = a1[i];
		a8[i] = a1[i];
	}

	int begin1 = clock();
	//InsertSort(a1, N);
	int end1 = clock();

	int begin2 = clock();
	ShellSort(a2, N);
	int end2 = clock();

	int begin3 = clock();
	//SelectSort(a3, N);
	int end3 = clock();

	int begin4 = clock();
	HeapSort(a4, N);
	int end4 = clock();

	int begin5 = clock();
	QuickSort(a5, 0, N - 1);
	int end5 = clock();

	int begin6 = clock();
	MergeSort(a6, N);
	int end6 = clock();

	int begin7 = clock();
	//BubbleSort(a7, N);
	int end7 = clock();

	int begin8 = clock();
	CountSort(a8, N);
	int end8 = clock();

	printf("InsertSort:%d\n", end1 - begin1);
	printf("ShellSort:%d\n", end2 - begin2);
	printf("SelectSort:%d\n", end3 - begin3);
	printf("HeapSort:%d\n", end4 - begin4);
	printf("QuickSort:%d\n", end5 - begin5);
	printf("MergeSort:%d\n", end6 - begin6);
	printf("BubbleSort:%d\n", end7 - begin7);
	printf("CountSort:%d\n", end8 - begin8);

	free(a1);
	free(a2);
	free(a3);
	free(a4);
	free(a5);
	free(a6);
	free(a7);
	free(a8);
}

int main()
{
	//TestInsertSort();
	//TestBubbleSort();
	//TestShellSort();
	//TestSelectSort();
	//TestHeapSort();
	//TestQuickSort();
	//TestMergeSort();
	//TestCountSort();

	TestOP();

	return 0;
}
举报

相关推荐

0 条评论