冒泡排序,插入排序,快速排序,归并排序,堆排序,选择排序,希尔排序

#include<iostream>
using namespace std;
void swap(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}
void print(int a[], int n)
{
	printf("\n");
	for (int i = 0; i < n; i++)
	{
		printf("  %d  ", a[i]);
	}
}
//冒泡排序
void bubblesort(int a[], int n)
{
	for (int i = n - 1; 0 < i; i--)
	{
		for (int j = 0; j <i; j++)
		{
			if (a[j]>a[j + 1])
			{
				swap(a[j], a[j + 1]);
			}
		}
	}
}
//插入排序
void insertsort(int a[], int n)
{
	for (int i = 1; i < n; i++)
	{
		int temp = a[i];
		int j = i;
		while ((temp < a[j - 1]) && j>0)
		{
			a[j] = a[j - 1];//右移
			j--;
		}
		a[j] = temp;
	}
}
void shell_sort1(int a[], int n)//希尔排序--也称为分组插入排序!!!!
{
	int i, j, gap;

	// gap为步长,每次减为原来的一半。
	for (gap = n / 2; gap > 0; gap /= 2)//回合
	{
		// 共gap个组,对每一组都执行直接插入排序
		for (i = 0; i < gap; i++)///组数
		{
			for (j = i + gap; j < n; j += gap)//相当于	for (int i = 1; i < n; i++)
			{
				// 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
					int tmp = a[j];
					while (j >= 0 && a[j-gap] > tmp)//	while ((temp < a[j - 1]) && j>0)
					{
						a[j] = a[j-gap];
						j-= gap;
					}
					a[j] = tmp;
			
			}
		}

	}
}
//快速排序
void quicksort(int a[], int lo, int hi)
{
	int base = a[lo];
	int i = lo;
	int j = hi;

	while (i <= j)
	{
		while (base > a[i]) i++;
		while (base < a[j])  j--;

		if (i <= j)//没有等号就出不来了
		{
			swap(a[i], a[j]);
			i++;
			j--;
		}
	}
	if (lo < j) quicksort(a, lo, j);
	if (i < hi) quicksort(a, i, hi);
}
//归并排序
void Merge(int array[], int left, int mid, int right)// 归并排序中的合并算法  
{
	
	int aux[20] = { 0 };  // 临时数组 (若不使用临时数组,将两个有序数组合并为一个有序数组比较麻烦)  
	int i=left; //第一个数组索引  
	int j = mid + 1; //第二个数组索引  
	int k; //临时数组索引  

	for ( k = 0; k <= right - left; k++) // 分别将 i, j, k 指向各自数组的首部。  
	{
		//若 i 到达第一个数组的尾部,将第二个数组余下元素复制到 临时数组中  
		if (i == m + 1)
		{
			aux[k] = array[j++];
			continue;
		}
		//若 j 到达第二个数组的尾部,将第一个数组余下元素复制到 临时数组中  
		if (j == right + 1)
		{
			aux[k] = array[i++];
			continue;
		}
		//如果第一个数组的当前元素 比 第二个数组的当前元素小,将 第一个数组的当前元素复制到 临时数组中  
		if (array[i] < array[j])
		{
			aux[k] = array[i++];
		}
		//如果第二个数组的当前元素 比 第一个数组的当前元素小,将 第二个数组的当前元素复制到 临时数组中  
		else
		{
			aux[k] = array[j++];
		}
	}

	  
	//i = left , 被排序的数组array 的起始位置  
	//j = 0, 临时数组的起始位置  
	for (i = left, j = 0; i <= right; i++, j++)
	{
		array[i] = aux[j];//将有序的临时数组 元素 刷回 被排序的数组 array 中,
	}
}
void MergeSort(int array[], int lo, int hi)
{
	if (lo < hi)//终止条件了
	{
		int mid = (lo + hi) / 2;

		// 对前半部分进行排序  ---------------------先是无限切分,,,,再从底部往上归并
		MergeSort(array, lo, mid);
		// 对后半部分进行排序  
		MergeSort(array, mid + 1, hi);
		// 合并前后两部分  
		Merge(array, lo, mid, hi);

	}
}
//堆排序

void HeapAdjust(int a[], int m, int n)//构造大根堆(让a[m]到a[n]满足大根堆)
{
	int max;
	int lc;//左孩子
	int rc;//右孩子

	while (1)//weile 循环
	{
		//获取a[m]的左右孩子
		lc = 2 * m + 1;
		rc = 2 * m + 2;
		//比较a[m]的左右孩子,max记录较大者的下标
		if (lc >= n)//终止条件
		{
			break;//不存在左孩子则跳出
		}
		if (rc >= n)
		{
			max = lc;//不存在右孩子则最大孩子为左孩子
		}
		else
		{
			max = a[lc] > a[rc] ? lc : rc;//左右孩子都存在则找出最大孩子的下标
		}
		//判断并调整(交换)
		if (a[m] >= a[max])//父亲比左右孩子都大,不需要调整,直接跳出
		{                         
			break;
		}
		else
		{//否则把小父亲往下换
			swap(a[m], a[max]);
			m = max;   //准备下一次循环,注意力移动到孩子身上,因为交换之后以孩子为根的子树可能不满足大根堆
		}
	}
}

void HeapSort(int a[], int n)
{
	int i, j;
	for (i = n / 2 - 1; i >= 0; i--)//自下而上构造大根堆(初始堆)
	{//a[n/2 - 1]恰好是最后一个非叶子节点(叶子节点已经满足小根堆,只需要调整所有的非叶子节点),一点小小的优化
		HeapAdjust(a, i, n);
	}
    for (i = n - 1; i > 0; i--)
	{
		swap(a[i], a[0]);//首尾交换,断掉尾巴
		HeapAdjust(a, 0, i);//断尾后的部分重新调整  一直i--,,从下标0开始重新建堆到i
	}
}


//选择排序
void selectsort(int a[], int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int k = i;
		for (int j = i + 1; j < n; j++)
		{
			if (a[j] < a[i])
			{
				k = j;
			}
		}
		swap(a[k], a[i]);

	}
}
//基数排序

void main()
{
	//int a[5] = { 2, 4, 1, 3, 0 };
	int a[20] = { 0, 1, 17, 3, 4, 5, 13, 18, 11, 9, 10, 8, 12, 6, 14, 15, 16, 2, 7, 19 };
	printf("排序前:\n");
	print(a, 20);
	//bubblesort(a, 5);
	//insertsort(a, 20);
	shell_sort1(a, 20);

	//quicksort(a, 0, 19);
	//selectsort(a, 5);
	//HeapSort(a, 5);
	//MergeSort(a, 0, 4);
	//shellSort(a,20);
	printf("\n排序后:\n");

	print(a, 20);

	getchar();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值