常用排序算法的c++语言实现(2)

2 篇文章 0 订阅
2 篇文章 0 订阅

承接上一篇的常用排序算法的c++语言实现
**4.希尔排序:**把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止
**5.快速排序:**通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
**6.归并排序:**一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
**7.堆排序:**利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

#include<iostream>
using namespace std;

//遍历数组
void traverse(int* arr, int len) {
	for (int i = 0; i < len; i++) {
		cout << arr[i] << " ";
	}
	cout << endl;
}
//交换函数
void swap(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}
//冒泡排序
void Bubble_Sort(int* a, int len) {
	for (int i = 0; i < len - 1; i++) {
		int flag = 0;
		for (int j = 0; j < len - 1 - i; j++) {
			if (a[j] > a[j+1]) {
				swap(a[j], a[j+1]);
				flag = 1;
			}
		}
	    if (flag == 0)break;
	}
}
//选择排序,不稳定
void Selection_Sort(int* arr, int len) {
	for (int i = 0; i < len - 1; i++) {
		int index = i;
		for (int j = 1 + i; j < len; j++) {
			if (arr[index] > arr[j]) {
				index = j;
			}
		}
		swap(arr[index], arr[i]);
	}
}
//插入排序
void Insertion_Sort(int* arr, int len) {
	for (int i = 0; i < len-1 ; i++) {
		for (int j = i; j >=0; j--) {
			if (arr[j] > arr[j + 1]) {
				swap(arr[j], arr[j + 1]);
			}
			else break;
		}
	}
}
//希尔排序:更高效的插入排序,不稳定
void Shell_Sort(int* arr, int len) {
	for (int gap = len / 2; gap > 0; gap /= 2) {
		for (int i = gap; i < len; i++) {
			for (int j = i - gap; j >= 0; j -= gap) {
				if (arr[j] > arr[j + gap]) {
					swap(arr[j], arr[j + gap]);
				}
				else break;
			}
		}
	}
}
//快速排序,不稳定
void Quick_Sort(int* arr, int left, int right) {
	int l = left;// 左下标
	int r = right;// 右下标
	int pivot = arr[(left + right) / 2];// 找到中间的值
	// 将比pivot小的值放在其左边,比pivot大的值放在其右边
	while (l < r) {
		// 在pivot左边寻找,直至找到大于等于pivot的值才退出
		while (arr[l] <pivot) {
			l += 1;// 将l右移一位
		}
		// 在pivot右边寻找,直至找到小于等于pivot的值才退出
		while (arr[r] > pivot) {
			r -= 1;// 将r左移一位
		}
		if (l >= r) {
			// 左右下标重合,寻找完毕,退出循环
			break;
		}
		// 交换元素
		swap(arr[r], arr[l]);
		//倘若发现值相等的情况,则没有比较的必要,直接移动下标即可
		// 如果交换完后,发现arr[l]==pivot,此时应将r左移一位
		if (arr[l] == pivot) {
			r -= 1;
		}
		// 如果交换完后,发现arr[r]==pivot,此时应将l右移一位
		if (arr[r] == pivot) {
			l += 1;
		}
	}
	// 如果l==r,要把这两个下标错开,否则会出现无限递归,导致栈溢出的情况
	if (l == r) {
		l += 1;
		r -= 1;
	}
	// 向左递归
	if (left < r) {
		Quick_Sort(arr, left, r);
	}
	// 向右递归
	if (right > l) {
		Quick_Sort(arr, l, right);
	}
}
//归并排序
void merge(int* arr, int left, int right, int mid, int* temp) {
	int i = left; // 初始化i,左边有序序列的初始索引
	int j = mid + 1;// 初始化j,右边有序序列的初始索引(右边有序序列的初始位置即为中间位置的后一个位置)
	int t = 0;// 指向temp数组的当前索引,初始为0
	// 先把左右两边的数据(已经有序)按规则填充到temp数组
	// 直到左右两边的有序序列,有一边处理完成为止
	while (i <= mid && j <= right) {
		// 如果左边有序序列的当前元素小于或等于右边有序序列的当前元素,就将左边的元素填充到temp数组中
		if (arr[i] <= arr[j]) {
			temp[t] = arr[i];
			t++;// 索引后移
			i++;// i后移
		}
		else {
			// 反之,将右边有序序列的当前元素填充到temp数组中
			temp[t] = arr[j];
			t++;// 索引后移
			j++;// j后移
		}
	}
	// 把有剩余数据的一边的元素填充到temp中
	while (i <= mid) {
		// 此时说明左边序列还有剩余元素
		// 全部填充到temp数组
		temp[t] = arr[i];
		t++;
		i++;
	}
	while (j <= right) {
		// 此时说明左边序列还有剩余元素
		// 全部填充到temp数组
		temp[t] = arr[j];
		t++;
		j++;
	}
	// 将temp数组的元素复制到原数组
	t = 0;
	int tempLeft = left;
	while (tempLeft <= right) {
		arr[tempLeft] = temp[t];
		t++;
		tempLeft++;
	}
}
void Merge_Sort(int*arr, int left, int right, int* temp) {
	// 分解
	if (left < right) {
		int mid = (left + right) / 2;// 中间索引
		// 向左递归进行分解
		Merge_Sort(arr, left, mid, temp);
		// 向右递归进行分解
		Merge_Sort(arr, mid + 1, right, temp);// mid + 1,中间位置的后一个位置才是右边序列的开始位置
		// 每分解一轮便合并一轮
		merge(arr, left, right, mid, temp);
	}
}
//堆排序
// 调整使之成为最大堆
 void adjustHeap(int*arr, int i,int len) {
	int maxIndex = i;
	//如果有左子树,且左子树大于父节点,则将最大指针指向左子树
	if (i * 2 < len && arr[i * 2] > arr[maxIndex])
		maxIndex = i * 2;
	//如果有右子树,且右子树大于父节点,则将最大指针指向右子树
	if (i * 2 + 1 < len && arr[i * 2 + 1] > arr[maxIndex])
		maxIndex = i * 2 + 1;
	//如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
	if (maxIndex != i) {
		swap(arr[maxIndex],arr[i]);
		adjustHeap(arr, maxIndex,len);
	}
}
 //构建最大堆函数
 void Build_MaxHeap(int* arr, int len) {
	 //从最后一个非叶子节点开始向上构造最大堆
	 for (int i = (len / 2 - 1); i >= 0; i--) {
		 adjustHeap(arr, i, len);
	 }
 }
 void Heap_Sort(int* arr, int len) {
	 //1.构建最大堆
	 Build_MaxHeap(arr, len);
	 //2.循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
	 while (len > 0) {
		 swap(arr[0], arr[len - 1]);
		 len--;
		 adjustHeap(arr, 0,len);
	 }
 }
int main() {
	int arr[10] = { 1,3,5,7,9,2,4,6,8,0 };
	int len = sizeof(arr) / sizeof(arr[0]);
	traverse(arr, len);
	Bubble_Sort(arr, len);
	Selection_Sort(arr, len);
	Insertion_Sort(arr, len);
	Shell_Sort(arr,len);
	int left = 0;
	int right = 9;
	Quick_Sort(arr, left, right);
	int* temp = new int[10];
	Merge_Sort(arr, left, right,temp);
	Heap_Sort(arr, len);
	traverse(arr, len);
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值