冒泡、插入、选择、归并排序

1 冒泡排序

算法原理:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。

  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

 

时间/空间复杂度:

若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数  和记录移动次数  均达到最小值:

  ,  。

所以,冒泡排序最好的时间复杂度为  。
若初始文件是反序的,需要进行  趟排序。每趟排序要进行  次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:

冒泡排序的最坏时间复杂度为  。

综上,因此冒泡排序总的平均时间复杂度为  ,冒泡排序的空间复杂度为O(1)。

 

代码实现:

void swap(int &num1, int &num2){
	int tmp = num1;
	num1 = num2;
	num2 = tmp;
}


//冒泡排序:升序
void BubbleSort(std::vector<int> &nums){
	int size = nums.size();
	if (size < 2)
		return;
	int i, j;
	for (i = 0; i < size; ++i)
		for (j = 1; j < size - i; ++j){
			if (nums[j] < nums[j-1])
				swap(nums[j], nums[j-1]);
		}
}

 

2 插入排序(直接插入)

算法原理:

⒈ 从第一个元素开始,该元素可以认为已经被排序。

⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描。

⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置。

⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置。

⒌ 将新元素插入到下一位置中。

⒍ 重复步骤2~5。

 

时间/空间复杂度:

时间复杂度最好为,最差为  ,冒泡排序的空间复杂度为O(1)。

 

代码实现:

void swap(int &num1, int &num2){
	int tmp = num1;
	num1 = num2;
	num2 = tmp;
}


//插入排序:升序
void InsertSort(std::vector<int> &nums){
	int size = nums.size();
	if (size < 2)
		return;
	int i, j;
	for (i = size - 1; i > 0; --i)
		for (j = size - i; j > 0; --j){
			if (nums[j] < nums[j - 1])
				swap(nums[j], nums[j - 1]);
		}
}

 

3 选择排序(直接选择)

算法原理:

每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。也就是:每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。

 

时间/空间复杂度:

时间复杂度最好为,最差为  ,冒泡排序的空间复杂度为O(1)。

 

代码实现:

void swap(int &num1, int &num2){
	int tmp = num1;
	num1 = num2;
	num2 = tmp;
}


//选择排序:升序
void SelectSort(std::vector<int> &nums){
	int size = nums.size();
	if (size < 2)
		return;
	int i, j;
	int minNum = 0;
	int minIndex = 0;
	for (i = 0; i < size; ++i){
		minNum = nums[i];
		minIndex = i;
		for (j = i + 1; j < size; ++j){
			if (nums[j] < minNum){
				minNum = nums[j];
				minIndex = j;
			}
		}
		swap(nums[i], nums[minIndex]);
	}
}

 

4 归并排序

算法原理:

归并排序可以看这个博客讲的不错:https://www.cnblogs.com/skywang12345/p/3602369.html

 

时间/空间复杂度:

时间复杂度最好为O(nlogn),最坏为O(nlogn),空间复杂度为O(n)。

 

代码实现:

//归并排序-升序
void MergeSort(std::vector<int> &nums, int left, int right){
	if (left == right)
		return;

	int mid = (left + right) / 2;
	if (left < right){
		MergeSort(nums, left, mid);
		MergeSort(nums, mid + 1, right);
		Merge(nums, left, mid, right);
	}
}


void Merge(std::vector<int> &nums, int left, int mid, int right){
	int i = left;//左序列指针
	int j = mid + 1;//右序列指针
	int size = right - left + 1;
	std::vector<int> tmp(size);
	int cnt = 0;
	while (i <= mid && j <= right){
		nums[i] <= nums[j] ? tmp[cnt++] = nums[i++] : tmp[cnt++] = nums[j++];
	}
	while (i <= mid) {//将左边剩余元素填充进temp中
		tmp[cnt++] = nums[i++];
	}
	while (j <= right){//将右序列剩余元素填充进temp中
		tmp[cnt++] = nums[j++];
	}
	cnt = 0;
	//将temp中的元素全部拷贝到原数组中
	while (left <= right){
		nums[left++] = tmp[cnt++];
	}
}

 

额外知识点:(1)小和问题     

                      (2)逆序对问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值