插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序(详细注释)

**

插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序

**

在这里#include<iostream>
#include<assert.h>

using namespace std;

void InsertSort(int *arr,int sz)//插入排序
{
	for (int i = 0; i < sz-1; i++)
	{
		int end = i;
		int key = arr[end + 1];
		while (end >= 0)
		{
			if (arr[end] > key)
			{
				arr[end + 1] = arr[end];
				--end;
			}
			else
				break;
		}
		arr[++end] = key;
	}
}

void ShellSort(int *arr,int s)//希尔排序
{
	int gap = s;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < s - gap ;i++)
		{
			int end = i;
			int key = arr[end+gap];
			while (end>0)
			{
				if (arr[end] > key)
				{
					arr[end + gap] = arr[end];
					end = end - gap;
				}
				else
					break;
			}
			arr[end+gap] = key;
		}
		
	}
}

void Swap(int &a, int &b)
{
	if (a > b)
	{
		int temp = a;
		a = b;
		b = temp;
	}
}

void Bubble(int *arr, int sz)//假冒泡排序
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = i + 1; j < sz ; j++)
		{
			if (arr[i]>arr[j])
				Swap(arr[i], arr[j]);
		}
	}
}

void Bubble1(int *arr, int sz)//冒泡排序
{
	for (int i = 0; i < sz - 1; ++i)
	{
		for (int j = 0; j < sz-1-i; ++j)//为什么是sz-1-i呢,当内层循环到sz-1是,arr[j]是倒数第二个数,arr[j+1]是最后一个数,
		{
			if(arr[j]>arr[j+1])
			Swap(arr[j],arr[j+1]);
		}
	}
}

void Bubble2(int *arr, int sz)//添加标志位的冒泡排序,可以减少没必要的比较
{
	/*mark的作用arr2[]数组可以体现出来,当外层循环一次后,排序已经完毕。如若按Bubble1的算法,只有当内外层的所有循环跑完后,程序才会终止。而Bubble2中的mark,外层进行第二次循环时,内层循环没有调换过次序,mark标志会一直是0,当外层循环进入第三次循环时,由于mark=0,循环条件不成立,所以整个循环就终止了。从而大量减少了不必要的循环比较。*/
	int mark = 1;
	for (int i = 0; i < sz - 1&&mark; ++i)
	{
		mark = 0;
		for (int j = 0; j < sz - 1 - i; ++j)
		{
			if (arr[j]>arr[j + 1])
			{
				Swap(arr[j], arr[j + 1]);
				mark = 1;
			}
		}
	}
}

void QuickSort(int *arr,int left,int right)//快速排序,左右指针法
{
	int key = right;
	int begin = left;
	int end = right;
	while (left >= right)
	{
		return;
	}
	while (left < right)
	{
		while (left < right&&arr[left] <= arr[key])
			left++;
		while (left < right&&arr[right] >= arr[key])
			right--;
		if (left < right&&arr[left] != arr[right])
		{
			Swap(arr[left], arr[right]);
		}
	}
	
	Swap(arr[left],arr[key]);
	QuickSort(arr, begin, left - 1);//递归对当前key值左侧数组进行排序,right=key=key前一个数值,begin=key左侧最左边的值。
	QuickSort(arr,left+1,end);//递归对当前key值右侧的数组进行排序,begin=当前key值后一个位置上的数值,key=right=右侧最右边的值
}

void QuickSort1(int *arr, int left, int right)//快速排序,挖坑法
{
	while (left >= right)
		return;

	int hollow = right;
	int begin = left;
	int end = right;
	int key = arr[right];
	
	while (left < right)
	{
		while (left < right&&arr[left] <= key)
			left++;
		arr[hollow] = arr[left];
		hollow = left;

		while (left < right&&arr[right] >= key)
			right--;
		arr[hollow] = arr[right];
		hollow = right;
		
	}
	if (left == right)
	{
		arr[left] = key;
	}
	QuickSort1(arr, begin, left - 1);
	QuickSort1(arr, left + 1, end);
}

/*
void QuickSort2(int *arr, int left, int right)//挖坑法改进,代码有问题
{
	while (left >= right)
		return;
	int hollow = right;
	int begin = left;
	int end = right;
	int key = arr[right];
	while (left < right)
	{
		while (left < right&&arr[left] < key)
			left++;
		Swap(arr[hollow], arr[left]);
		hollow = left;
		while (left<right&&arr[right]>key)
			right--;
		Swap(arr[hollow], arr[right]);
		hollow = right;
	}
	QuickSort2(arr, begin, left - 1);
	QuickSort2(arr, left + 1, end);

}
*/

void SelectSort(int *arr, int sz)//选择排序
{
	int i, j, min;
	for (i = 0; i < sz; ++i)
	{
		min = i;
		for (j = i + 1; j < sz; ++j)
	/*i=0第一次循环,把i=0右边剩余的元素一一和第一个元素对比,比第一个小的,把其下表赋给min,在继续向后找,如果有更小的,更新min。次时已经找出整个数组中最小的值。然后,i=1从第二次循环,把i=1右边剩余的元素一一和第二个元素对比,比第二个小的,把其下表赋给min,在继续向后找,如果有更小的,更新min。次时已经找出整个数组中最小的值。以此类推。。。。*/
		{
			if (arr[j] < arr[min])
				min = j;
		}
		//if (min != i)//词条语句多余,内层循环循环完之后,自然就找出除已经排好序元素之外的最小元素。
			Swap(arr[i], arr[min]);
	}
}

void AdjustDown(int *arr,int father,int sz)//堆的建立(默认为大堆)
{
	int child = father * 2 + 1;
	while (child < sz)
	{
		if (child + 1 < sz&&arr[child + 1] > arr[child])//确保孩子节点中较大的与父节点交换
		{
			child++;
		}
		if (arr[child]>arr[father])
		{
			Swap(arr[child], arr[father]);
			father = child;
			child = father * 2 + 1;
		}
		else
			return;
	}
}

void AdjustUp(int *arr, int father, int sz)//堆的建立(小堆)
{
	int child = father * 2 + 1;
	while (child < sz)
	{
		if (child + 1 < sz&&arr[child] > arr[child + 1])
			child++;
		if (arr[child] < arr[father])
		{
			swap(arr[child], arr[father]);
			father = child;
			child = father * 2 + 1;
		}
		else
			return;
	}
}

void HeapSort(int *arr, int sz)//堆排序
{
	int i = 0;
	for (i = (sz - 2) / 2; i >= 0; i--)
	{
		AdjustDown(arr, i, sz);//建立堆,大堆
	}
	while (sz > 1)
	{
		sz--;
		swap(arr[0], arr[sz]);//首元素和最后一个元素交换,最大元素就被排在最后,对剩余的元素堆化。重复此过程
		AdjustDown(arr, 0, sz);
	}
}

void HeapSort1(int *arr, int sz)//堆排序,
{
	int i = 0;
	for (i = (sz - 2) / 2; i >= 0; i--)
	{
		AdjustUp(arr, i, sz);//建立堆,小堆
	}
	while (sz > 1)
	{
		sz--;
		swap(arr[0], arr[sz]);//首元素和最后一个元素交换,最小元素就排在最后,对剩余的元素堆化。重复此过程。
		AdjustUp(arr, 0, sz);
	}
}

void Merge(int *arr, int *temp, int begin1, int end1, int begin2, int end2)//合并数组
{
	int pos = begin1;//pos用来记录原始数组当前所在的位置
	int index = begin1;//index用来记录新开辟数组到当前所在的位置
	while (begin1 <= end1&&begin2 <= end2)//比较两个有序区间值的大小,对有序区间进行合并
	{
		if (arr[begin1] < arr[begin2])
			temp[index++] = arr[begin1++];
		else
			temp[index++] = arr[begin2++];
	}
	while (begin1 <= end1)//对部分有序区间进行合并
	{
		temp[index++] = arr[begin1++];
	}
	while (begin2 <= end2)
	{
		temp[index++] = arr[begin2++];
	}
	memcpy(arr + pos, temp + pos, sizeof(int)*(end2 - pos + 1));//从temp+pos所指的内存地址的起始位置开始,拷贝(end2-pos+1)个字节的数据到目标arr+pos所指的内存地址的起始位置中
}

void _Merge(int *arr,int *temp,int left,int right)//分裂数组
{
	if (left >= right)
		return;
	int mid = left + (right - left) / 2;
	_Merge(arr,temp,left,mid);//分裂数组
	_Merge(arr, temp, mid+1, right);//分裂数组
	Merge(arr,temp,left,mid,mid+1,right);//合并数组
}

void MerageSort(int *arr, int sz)//归并排序
{
	int *tmp = new int[sz];
	_Merge(arr, tmp, 0, sz - 1);
	delete []tmp;
}

void Print(int *arr, int sz)
{
	for (int i = 0; i < sz; i++)
		cout << arr[i] << ' ';
	cout << endl;
}

int main()
{
	int arr[] = { 5, 7, 6, 4, 9, 2, 8, 1, 3};
	int arr1[] = { 10, 90, 40, 54, 63, 78, 11, 52, 45, 65, 79 };
	int arr2[] = {9,1,2,3,4,5,6,7,8};
	int arr3[] = {9,8,7,6,5,4,3,2,1,0};
	int arr4[] = {90, 10, 50, 80, 30, 70, 40, 60, 20};
	int arr_4[] = { 90, 10, 50, 80, 30, 70, 40, 60, 20 };
	int arr5[] = {10,30,50,20,90,60,80,70,40};
	//cout << "冒泡排序:";
	//int sz = sizeof(arr) / sizeof(arr[0]);
	//InsertSort(arr, sz);//插入排序
	//Print(arr, sz);
	//Bubble2(arr2, sz);//冒泡排序
	//Print(arr2, sz);

	cout << "希儿排序:";
	int sz1 = sizeof(arr1) / sizeof(arr1[0]);
	ShellSort(arr1, sz1);//希尔排序
	Print(arr1, sz1);

	cout << "快速排序:";
	int sz = sizeof(arr) / sizeof(arr[0]);
	QuickSort(arr, 0,sz-1);//快速排序
	Print(arr, sz);

	cout << "选择排序:";
	int sz3 = sizeof(arr3) / sizeof(arr3[0]);
	SelectSort(arr3, sz3);
	Print(arr3, sz3);

	cout << "堆排序:";
	int sz4 = sizeof(arr4) / sizeof(arr4[0]);
	HeapSort(arr4, sz4);//用大堆,升序排序
	Print(arr4,sz4);

	cout << "(小)堆排序:";
	int sz_4 = sizeof(arr_4) / sizeof(arr_4[0]);
	HeapSort1(arr_4, sz_4);//利用小堆,降序排序
	Print(arr_4, sz_4);


	cout << "归并排序:";
	int sz5 = sizeof(arr5) / sizeof(arr5[0]);
	MerageSort(arr5, sz5);
	Print(arr5,sz5);

	system("pause");
	return 0;
}插入代码片
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值