[C++算法]六种简单算法

#define SIZE_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))

void swap(int &a,int &b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

#define OUT_PUT_DEBUG_ARRAY(x,len) do \
{\
	for (int i = 0; i < len; i++)\
	{\
		printf("%6d",x[i]);\
	}\
	printf("\r\n--------------------------\r\n");\
} while (0);


// 0.冒泡排序
// 从头开始,依次遍历所有元素,当遇到比当前元素小的,直接交换
void BubbleSort_Wrong(int *arr, int len)
{
	for (int i = 0; i < len - 1; ++i)
	{
		for (int j = i + 1; j < len; ++j)
		{
			if (arr[i] > arr[j])
			{
				swap(arr[i], arr[j]);
			}
		}
	}
}

void BubbleSort_Right(int *arr, int len)
{
	for (int i = 0; i < len - 1; ++i)
	{
		int nMax = arr[i];
		for (int j = 0; j < len - 1 - i; ++j)
		{
			if (arr[j + 1] > arr[j])
			{
				swap(arr[j + 1], arr[j]);
			}
		}
	}
}

// 1.选择排序
// 从头开始,依次遍历所有元素,找出当前坐标到结尾最小的元素,进行交换
// 思想与冒泡排序差不多,只不过交换放到了循环外,减少了交换次数
void SelectSort(int *arr, int len)
{
	for (int i = 0;i < len - 1;++i)
	{
		int k = i;
		for (int j = i + 1;j < len;++j)
		{
			//if (arr[i] > arr[j]) -- 此处错误,多谢指正@_@ @tuohaohu
			if (arr[k] > arr[j])
			{
				k = j;
			}
		}
		if (i != k)
		{
			swap(arr[i], arr[k]);
		}	
	}
}

// 2.插入排序
// 总所周知,当只有一个元素时,待排数据为有序数据
// 假定数组arr[n],当 0 < k < n时,a[0]~a[k-1]有序,a[k]~a[n-1]无序
// 此时,将arr[k]拿出来,将arr[0]~arr[k-1]从k-1开始往左遍历,如果a[j] > a[k],则将a[j]左移,指导a[j] < a[k],此时将a[k]放到a[j+1],arr[0]~arr[k]变为有序序列
// 当遍历晚arr[n]时,此时数据将为有序序列
void InsertSort(int *arr, int len)
{
	if (len <= 1)
	{
		return;
	}

	for (int i = 1; i < len;++i)
	{
		int tmp = arr[i];
		for (int j = i - 1;j >= 0;--j)
		{
			if (arr[j] >= tmp)
			{
				arr[j + 1] = arr[j];
			}
			else
			{
				arr[j + 1] = tmp;
				break;
			}
		}
	}
}


// 3.二分插入排序
// 因为直接插入排序在搜索插入位置的时候,效率很低,对于大数组,尤其不适用
// 于是采用二分插入排序,又叫折半插入排序, 二分插入排序是采用折半查找法寻找要插入的位置 
// 二分搜索:
void  BinaryInsertSort(int *arr, int len)
{
	for (int i = 1; i < len; ++i)
	{
		int tmp = arr[i];
		int iHigh = i - 1;
		int iLow  = 0;
		int iMid = 0;
		while (iLow <= iHigh)
		{
			iMid = (iLow + iHigh) / 2;
			if (tmp > arr[iMid] )
			{
				iLow = iMid + 1;
			}
			else
			{
				iHigh = iMid - 1;
			}
		}

		// 将 iMid 到 i 的数据左移
		for (int j = i; j > iMid; --j)
		{
			arr[j] = arr[j - 1];
		}
		arr[iLow] = tmp;
	}
}

// 4.归并排序
// 将待排序数据,从中间分为2段A和B,使A和B分别有序后,再将A和B使用插入排序
// 退出条件为
void MergeSort(int *arr, int beg,int end)
{
	//OUT_PUT_DEBUG_ARRAY(&arr[beg], end - beg);
	if (beg >= end)
	{
		return;
	}

	if (beg == end - 1)
	{
		if (arr[beg] > arr[beg + 1])
		{
			swap(arr[beg], arr[beg + 1]);
		}	
		return;
	}

	// 将beg到end分为2段A和B,并将A和B分别使用归并排序
	int iL1 = beg;
	int iH1 = (beg + end) / 2;
	int iL2 = iH1 + 1;
	int iH2 = end;
	MergeSort(arr, iL1, iH1);
	MergeSort(arr, iL2, iH2);
	
	// 将A 和 B 排序完毕后,合并A和B——使用插入排序 
	for (int i = iL2; i <= iH2; ++i)
	{
		int tmp = arr[i];
		for (int j = iH1 + i - iL2; j >= iL1; --j)
		{
			arr[j + 1] = arr[j];
			if (tmp > arr[j])
			{
				arr[j + 1] = tmp;
				break;
			}
		}
	}
}

// 5.快速排序
// 1.以左右两端i和j为起点,从右往左开始,找到比最左端小的数,停止坐标记为A,从左往右找到比最左端大的数,停止坐标记为A。交换A和B标记的数。
// 2.重复第一点,直到A == B,将此事的坐标所标识的值与最开始的数据交换。记此时的坐标为K
// 3.分别对 i~K-1 与 K+1 ~ j 重复上诉1、2两点
void quickSort(int *arr, int left, int right)
{
	if (left > right)
	{
		return;
	}

	int tmp = arr[left];
	int iLeft = left;
	int iRight = right;
	while (left != right)
	{
		while (right > left && (arr[right] >= tmp))
		{
			right--;
		}
		while (right > left && (arr[left] <= tmp))
		{
			left++;
		}
		if (left < right)
		{
			swap(arr[left], arr[right]);
		}		
	}

	
	arr[iLeft] = arr[left];
	arr[left] = tmp;

	quickSort(arr, iLeft, left - 1);
	quickSort(arr, left + 1, iRight);
}

  • 7
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值