mthoutai

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

排序算法复习大致结束了,主要有下面几种:冒泡排序、选择排序、简单插入排序、希尔排序、归并排序、高速排序、堆排序。

#include <iostream>

#define MAXSIZE 1000

using namespace std;

class SqList{
public:	
	SqList():length(0){}
	SqList(int length1,int value=0):length(length1)
	{
		for(int i=0;i<length;++i)
		{
			data[i]=value;
		}
	}
	
	bool insertTail(int value)
	{
		if(length>=MAXSIZE)
		{
			return false;
		}
		data[length]=value;
		length++;
		return true;
	}
	
	friend ostream& operator<<(ostream& output, SqList list);

	
public:
	int data[MAXSIZE];
	int length;
};

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

ostream& operator<<(ostream& output, SqList list)
{
	for (int i = 0; i<list.length; ++i)
	{
		output <<list.data[i] << "   ";
		if ((i + 1) % 18 == 0)
			output << endl;
	}
	output << endl;
	return output;
}

/**
 *冒泡排序即相邻的两者相互比較,依据需求把较大的或较小的前移或后移
 *记住,两两相邻的比較是冒泡排序的特点之中的一个
 */
void BubbleSort1(SqList* list)
{//每次遍历时把较大者后移
	int length=list->length;
	while(length>0)
	{
		for(int i=0;i<length-1;++i)
		{
			if(list->data[i] > list->data[i+1])
				swap(list->data[i],list->data[i+1]);
		}
		length--;
	}
}

void BubbleSort2(SqList* list)
{//每次遍历时,把较小的前移
	for(int i=0;i<list->length;i++)
	{
		for(int j=list->length-2;j>=i;j--)
		{
			if(list->data[j] > list->data[j+1])
				swap(list->data[j],list->data[j+1]);
		}
	}
	
}

/**
 *选取排序即每次在未排序队列其中选取一个最小值。然后与第i个值进行交换,直至i为length为止;
 *当然,也能够选取最大值把到后面,依据需求而定
 */

void selectSort(SqList* list)
{
	for (int i = 0; i < list->length; ++i)
	{
		int min = list->data[i];
		int pos = i;
		for (int j = i+1; j < list->length; ++j)
		{
			if (list->data[j] < min)
			{
				min = list->data[j];
				pos = j;
			}
		}
		if (pos != i)
		{
			swap(list->data[i], list->data[pos]);
		}
	}
}

/**
 *遍历链表,把每一个元素插入到正确位置
 */
void InsertSort1(SqList *list)
{
	for (int i = 1; i < list->length; ++i)
	{
		int j = i - 1;
		for (; j >=0; j--)
		{
			if (list->data[i] > list->data[j])
				break;
		}
		int tmp = list->data[i];
		for (int k = i; k > j+1; --k)
		{
			list->data[k] = list->data[k - 1];
		}
		list->data[j + 1] = tmp;
	}
}

void InsertSort2(SqList *list)
{
	for (int i = 1; i < list->length; ++i)
	{
		if (list->data[i] < list->data[i - 1])
		{
			int tmp = list->data[i];
			int j = i-1;
			for (; j >= 0 && list->data[j] > tmp; --j)
			{//查找的同一时候,进行后移操作
				list->data[j + 1] = list->data[j];
			}
			list->data[j + 1] = tmp;
		}
	}
}

/**
 *希尔排序是插入排序的一种改进。能够理解为把一个数组分成几个小的数组进行插入排序,再合并使原数组基本有序。
 *希尔排序一个非常关键的步骤是增量的选取。合适的增量能够提高排序效率,但不合适的增量可能会导致程序崩溃或结果错误。

*其次,希尔排序也不是一个稳定的排序算法,由于它是跳跃插入排序的。 *希尔排序仅仅是比前面几种O(n2)的效果稍好,并不会优于后面要提到的高速排序等算法。 */ void ShellSort(SqList* list) { int increment = list->length; do{ increment = increment / 3 + 1; for (int i = increment + 1; i < list->length; ++i) { if (list->data[i] < list->data[i - increment]) { int tmp = list->data[i]; int j = i - increment; for (; j >= 0 && list->data[j] > tmp; j -= increment) { list->data[j + increment] = list->data[j]; } list->data[j + increment] = tmp; } } } while (increment > 1); } /** *归并排序原理上相对照较简单,即两个有序数组合并为一个有序数组 *但实现起来相对照较复杂,要用到辅助空间 */ //合并过程 void Merge(int TR1[], int TR2[], int low, int mid, int high) {//将TR2归并入TR1中 int pos1 = low; int pos2 = mid + 1; for (int i = low; i <= high; ++i) { if (pos1 <= mid && pos2 <= high) { if (TR2[pos1]>TR2[pos2]) { TR1[i] = TR2[pos2]; pos2++; } else { TR1[i] = TR2[pos1]; pos1++; } } else if (pos1<=mid) { TR1[i] = TR2[pos1++]; } else { TR1[i] = TR2[pos2++]; } } } //排序过程 void Msort(int SR[],int TR1[], int low, int high) { int TR2[MAXSIZE + 1]; if (low < high) {//先所有存放到TR2中,再由TR2归并到TR1 int mid = (low + high) / 2; Msort(SR,TR2,low, mid); Msort(SR,TR2,mid + 1, high);//先将两个子序列排序,然后再合并 Merge(TR1, TR2, low, mid, high); } else { TR1[low] = SR[low]; } } void MergeSort1(SqList* list) { Msort(list->data,list->data,0,list->length-1); } void MergePass(int TR[], int SR[], int k, int length) { int i = 0; while (i <= length-2*k+1) {//两两合并 Merge(TR, SR, i, i + k-1, i + 2 * k - 1); i = i + 2 * k; } if (i <= length - k + 1) {//说明后面还剩两个子数组,一个是完整的k个,还有一个小于k Merge(TR, SR, i, i + k - 1, length); } else {//最后仅仅剩一个子数组, for (int j = i; j <= length; j++) { TR[j] = SR[j]; } } } void MergeSort2(SqList* list) { int* TR = new int[list->length]; int k = 1; while (k < list->length) {//两次转存,先从data转存到TR,再从TR转存到data; MergePass(TR, list->data, k, list->length - 1); k = k * 2; MergePass(list->data, TR, k, list->length - 1); k = k * 2; } } /** *高速排序将以枢轴为界。将原数组分为两个部分。枢轴曾经,值都小于枢轴的值,枢轴以后的值都大于枢轴 *採用递归的方法,对以枢轴为界的两个子序列进行高速排序,直至子序列长度为1 *1、高速排序的关键是枢轴的选取,主要有三种方法:1)选取第一个或最后一个作为枢轴值。 *2)採用随机数生成器,生成枢轴值的下标。3)取第一个、最后一个、中间三者的中间值作为枢轴值。

*2、高速排序由于要递归,当须要排序的数组量比較小时,使用普通的排序算法效果可能更好,所以又出现了一种优化方法。

*相较于归并排序和堆排序。高速排序是一种高效并且简单的排序方法。 */ int partion(SqList* list, int low, int high) { int key = list->data[high];//枢轴值 int fast = low; int slow = low; while (fast < high) { if (list->data[fast] < key) { if (slow != fast) { swap(list->data[fast], list->data[slow]); } fast++; slow++; } else { fast++; } } swap(list->data[slow], list->data[high]); return slow; } void qsort1(SqList* list,int low,int high) { if (low < high) { int index = partion(list,low,high); qsort1(list, low, index - 1);//高低子表都採用递归的方法实现 qsort1(list, index + 1, high); } } #define MAX_LENGTH_INSERT_SORT 7//定义插入排序能够接受的最大数组 void qsort2(SqList* list, int low, int high) { if ((high - low) > MAX_LENGTH_INSERT_SORT) { if (low < high) { int index = partion(list, low, high); qsort2(list, low, index - 1); qsort2(list, index + 1, high); } } else InsertSort2(list);//当然,此处不能直接使用,还须要对InsertSort2作一下改动。改成指定下标的形式 } //仅仅用一次递归。高子表採用迭代的方式,减小了递归的深度。

void qsort3(SqList* list, int low, int high) { if ((high - low) > MAX_LENGTH_INSERT_SORT) { if (low < high) { int index = partion(list, low, high); qsort2(list, low, index - 1); low = index + 1;//高子表不递归,採用迭代 } } else InsertSort2(list);//当然。此处不能直接使用,还须要对InsertSort2作一下改动,改成指定下标的形式 } void QuickSort(SqList* list) { qsort1(list,0,list->length-1); } /** *堆排序也没有想像中那么复杂,建堆和堆维护都能够用一个函数完毕; * */ void HeapAdjust(SqList* list, int obj, int length) { int tmp = list->data[obj - 1]; for (int j = 2*obj; j <= length; j *= 2) {//一定要注意下标和编号的不统一。堆排序開始编号是1,而本程序的数据结构開始编号是0。 //也就是说编号j相应的下标是j-1 if (j < length && list->data[j-1] < list->data[j]) j++; if (list->data[j-1] <= tmp) { break; } list->data[obj - 1] = list->data[j-1]; obj = j; } list->data[obj - 1] = tmp; } void HeapSort(SqList* list) { //第一次循环,建立最大堆 for (int i = list->length / 2; i > 0; i--) {//注意,传入的參数都是下标再加1 HeapAdjust(list, i, list->length); } //第二次循环,排序 for (int i = list->length; i > 0; i--) { swap(list->data[0],list->data[i - 1]); HeapAdjust(list, 1, i-1); } } int main() { SqList list; list.insertTail(5); list.insertTail(7); list.insertTail(9); list.insertTail(8); list.insertTail(4); list.insertTail(3); list.insertTail(1); list.insertTail(10); list.insertTail(16); list.insertTail(78); list.insertTail(0); cout<<"排序前:"<<endl; cout<<list<<endl; /*BubbleSort2(&list); cout<<"冒泡排序法:"<<endl; cout<<list<<endl;*/ /*selectSort(&list); cout << "选择排序法:" << endl; cout << list << endl;*/ /*InsertSort2(&list); cout << "插入排序法:" << endl; cout << list << endl;*/ /* ShellSort(&list); cout << "希尔排序法:" << endl; cout << list << endl;*/ //MergeSort1(&list); //cout << "归并排序:" << endl; //cout << list << endl; /*QuickSort(&list); cout << "高速排序:" << endl; cout << list << endl;*/ HeapSort(&list); cout << "堆排序:" << endl; cout << list << endl; return 0; }



posted on 2017-08-01 16:15  mthoutai  阅读(222)  评论(0编辑  收藏  举报