数据结构--排序算法(插入排序&&选择排序)

今天我们来总结一下数据结构中各种排序算法。

数据结构排序算法 part1:


直接插入排序:

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


简单来说:end指已经排好数组的最后一个元素,end找到插入的位置(设置一个temp,temp为已经排序好数组的下一个元素),用temp与end比较,如果temp<array[end],就把array[end]给array[end+1],然后把temp给array[end].
 
时间复杂度:O(N*N)
空间复杂度:O(1)
稳定性:如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

代码实现:
void Insert_Sort(int array[],int size)
{
	// 2, 5, 4, 9, 3, 6, 8, 7, 1, 0
	for (int idx = 0; idx < size-1; ++idx)
	{
		int temp = array[idx+1];
		int end = idx;
		while (end>=0 && array[end]>temp)
		{
			array[end+1] = array[end];
			end--;
		}	
		array[end+1] = temp;
	}
}

二分查找直接插入排序:

思想:在插入排序的基础上加入二分查找的思想,减少查找次数

时间复杂度:O(log(n))
空间复杂度:O(1)
稳定性:稳定的(同插入查找)
代码实现:
//二分查找插入排序
void Insert_Sort_P(int array[], int size)
{
	//这里idx从零开始是为了更好的贴近数组下标
	for (int idx = 0; idx < size - 1; ++idx)
	{	
		int temp = array[idx + 1];
		int end = idx;
		int left = 0;
		int right = end;
		
		//二分查找查找需要插入的区间
		while(left<=right)
		{
			int mid = left + ((right - left) >> 1);
			if (array[mid] > temp)
			{
				right = mid - 1;
			}
			//这里有等于 等于的话相同的插入到后面
			else
			{
				left = mid + 1;
			}
		}


		//这里比left的原因是因为right-1可能最后为负数
		while (end>=0&&end >= left)
		{
			array[end + 1] = array[end];
			end--;
		}
		//如果要是上面while没有执行 则此时temp还是end+1的值 这一步相当于没有做
		array[end + 1] = temp;
	}
}

希尔排序:
思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
 
时间复杂度:O(N^1.25) ---O(1.6N^1.25)
空间复杂度:O(1)
稳定性:不稳定
代码实现:
//希尔排序
void Shell_Sort(int array[],int size)
{
	int gap = size;
	//这里必须为>=1 因为可能最后间隔为1排
	while (gap >= 1)
	{
	gap = gap / 3 + 1;


		for (int idx = gap; idx < size; ++idx)
		{
			//这里temp为gap下标的值
			int temp = array[idx];
			int end = idx - gap;
			while (end >= 0 && array[end]>temp)
			{
				array[end + gap] = array[end];
				end -= gap;
			}
			array[end+gap] = temp;
		}
		gap--;
	}
}

选择排序:

思想:每一趟(例如第i趟,i=0,1,…,n-2)在后面n-i个待排序的数据元素集合中选出关键
码最小的数据元素,作为有序元素序列的第i个元素。待到第n-2趟做完,待排序元素集合中只剩下1个元素,排序结束。
 
时间复杂度:O(N*N)
空间复杂度:O(1)
稳定性:不稳定
代码实现:
//选择排序
void Select_Sort(int array[], int size)
{
	int min = 0;
	//几趟可以排完
	for (int idx = 0; idx < size; ++idx)
	{
		min = idx;
		for (int index = idx + 1; index < size; ++index)
		{
			if (array[min] > array[index])
				min = index;
		}


		if (min != idx)
		{
			std::swap(array[min], array[idx]);
		}
	}
}

选择排序的优化:
思想:一次选出一个最大的一个最小的,数组从两方缩进递减,把大的放到后面,小的放到前面。这时只用进行一半的次数,就可以对一组数排序完。
代码实现:
//选择排序优化
void Select_Sort_Cool(int array[],int size)
{
	int min = 0;
	int max = 0;
	int left;
	int right;
	for (left = 0, right = size - 1; left<=right; left++, right--)
	{
		min = left;
		max = right;
		for (int idx = left; idx <= right; ++idx)
		{
			if (array[min] > array[idx])
				min = idx;


			if (array[max] < array[idx])
				max = idx;
		}


		if (min != left)
		{
			std::swap(array[min], array[left]);
		}
		if (max != right)
		{
			std::swap(array[max], array[right]);
		}
	}
}


堆排序:

思想:利用大小堆对数据进行排序。建堆排序,每次排序后数组减一,把已经排好的元素剔除在外。
 
时间复杂度:O(NlogN)
空间复杂度:O(1)
稳定性:不稳定
代码实现:
//建堆 //根由上到下换
void adjust_Down(int array[],int root, int size)
{
	int child = root * 2 + 1;
	int parent = root;


	while (child < size)
	{
		if (child+1 < size && array[child] < array[child+1])
		{
			child = child + 1;
		}
		if (array[parent] < array[child])
		{
			std::swap(array[parent],array[child]);
			parent = child;
			child = child * 2 + 1;
		}
		else
			break;
	}
}
//堆排序
void Heap_Sort(int array[],int size)
{
	for (int idx = (size - 2) / 2; idx >= 0;--idx)
	{
		adjust_Down(array, idx, size);
	}
	int index = size - 1;
	while (index>0)
	{
		std::swap(array[0], array[index]);
		adjust_Down(array, 0, index);
		index--;
	}
}


冒泡排序&&快速排序&&鸽巢排序:http://blog.csdn.net/sayhello_world/article/details/76532423

归并排序&&基数排序&&桶排序:http://blog.csdn.net/sayhello_world/article/details/65631159

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值