排序算法总结

一、直接插入排序

1、基本思想:对于数组a[1...n],初始时,a[1]为一个有序区间,a[2...n]为无序区间,然后依次将a[2],a[3].....a[n]插入到有序区间内。

2、代码

/*直接插入排序*/
void InsertSort(int arr[], int length)
{
	for (int i = 1; i < length; i++)
	{
		int temp = arr[i];
		int j;
		for (j = i - 1; j >=0 && temp<arr[j] ; j--)//从后往前进行比较
		{
			arr[j+1] = arr[j];
		}
		arr[j + 1] = temp;
	}
}
3、稳定、时间复杂度O(n^2)  空间复杂度o(1)

二、希尔(shell)排序

1、基本思想:改进的的插入排序,首先将待排序列按照某个增量d分成几个组,每个组中记录下标相差d对每个组中的元素进行排序,然后减小d重新排序,直至d为1,整个序列变成一个组,排序完成。

2、代码

/*希尔排序(d开始为序列的一半,每次减半)*/
void ShellSort(int arr[], int length)
{
	
	for (int d = length / 2; d > 0; d = d / 2)
	{
		for (int i = 1; i < length; i++)
		{
			int temp = arr[i];
			int j;
			for (j = i - d; j >= 0 && arr[j]>temp; j-=d)
			{
				arr[j + d] = arr[j];
			}
			arr[j + d] = temp;
		}
	}
}
3、 不稳定 时间复杂度O(nlog2n) 空间复杂度o(1)

三、冒泡排序

1、基本思想:对于待排序列a,从头到尾扫描,将较大的数交换至最后的位置,直到整个序列有序

2、代码:

void Swap(int &a, int &b)//“或”实现两个数的交换
{
	a = a^b;
	b = b^a;
	a = a^b;
}
/*直接插入排序*/
void BubberSort(int arr[], int length)
{
	for (int i = 0; i < length-1; i++)
	{
		int exchange = 0; //添加变量记录本次遍历有无交换,若无已经有序,跳出循环
		for (int j = i + 1; j < length; j++)
		{
			if (arr[i]>arr[j])
			{
				swap(arr[j], arr[i]);
				exchange = 1;
			}
		}
		if (exchange != 1)
			return;
	}
}
3、稳定 时间复杂度O(n^2) 空间复杂度o(1)

四、快速排序

1、基本思想:采用分治法,将原问题分解为若干与原问题结构相似的子问题,递归解决。首先,选取关键字pivot将待排序列分为两个部分,一部分元素全部大于pivot,另一部分全部小于pivot,pivot的位置得到确定。然后再递归的对小于和大于pivot的序列进行快排。

2、代码

/*快速排序*/
void QuickSort(int arr[],int first,int last)
{
	int low = first;
	int high = last;
	int pivot = arr[low];
	if (low < high)
	{
		while (low < high)
		{
			while (low < high && arr[high] >= pivot)//注意先从高位开始比较
			{
				high--;
			}
			if (low < high)
				arr[low++] = arr[high];
			
			while (low < high && arr[low] <= pivot)
			{
				low++;
			}
			if (low < high)
				arr[high--] = arr[low];		
		}
		arr[low] = pivot;
		QuickSort(arr, first, low - 1);
		QuickSort(arr, low + 1, last);
	}
}

3、不稳定 时间复杂度o(nlog2n)  由于采用了递归空间复杂度o(logn) 


五、选择排序

1、基本思想:在待排序列的无序区间的a[i+1.....n]中,选择一个最小的数跟a[i] 交换

2、代码:

/*选择排序*/
void SelectSort(int arr[], int length)
{
	for (int i = 0; i < length-1; i++)
	{
		int min = arr[i];
		int index = i;

		for (int j = i+1; j < length; j++)
		{
			if (arr[j] < min)
			{
				min = arr[j];
				index = j;
			}
		}
		arr[index] = arr[i];
        arr[i] = min;		
	}
}

3、不稳定 时间复杂度 O(n^2) 空间复杂度O(1)


六、堆排序

1、基本思想:堆排序有两种大根堆(所有子节点都小于其父节点,即Ai<=A2i且Ai<=A2i+1),小根堆(所有子节点都小于其父节点,即Ai>=A2i且Ai>=A2i+1)。

2、代码

以大根堆为例,首先将待排数列建成一个堆

void Built_Maxheap(int arr[], int length)//建立堆
{
	heapSize = length-1;
	for (int  i = (length >> 1-1); i >= 0 ; i--) //n/2-1之前都是父节点,之后的节点都是子节点,只需要对父节点进行maxHeapify
	{
		maxHeapify(arr, i);
	}
}

然后再将最大关键字堆顶元素与无序区的最后一个元素交换

void MaxHeapSort(int arr[], int length)//堆排序
{
	Built_Maxheap(arr, length);

	for (int i = length - 1; i >= 1; i--)
	{
		swap(arr[0], arr[i]);
		heapSize--;
		maxHeapify(arr, 0);
	}

}

交换过后可能会导致新的根违反大根堆的定义,所以要进行调整

void maxHeapify(int arr[], int index)//堆的调整
{
	int max = index;
	int left = Left(index);
	int right = Right(index);

	if (left <= heapSize && arr[left] > arr[index])
		max = left;

	if (right <= heapSize && arr[right] > arr[max])
		max = right;

	if (max != index)//如果堆顶不是最大者,则交换,并递归调整堆
	{
		Swap(arr[index], arr[max]);
		maxHeapify(arr, max);
	}
}

其中,根节点的左右子树计算方法如下

void Swap(int &a, int &b)//用“^”完成交换操作
{
	a = a^b;
	b = b^a;
	a = a^b;
}

int Left(int i){ return ((i << 1) + 1); } //leftchild=2*i+1;返回左子节点索引
int Right(int i){ return ((i << 1) + 2); }//rightchild=2*i+2返回右子节点索引
int heapSize = 0;

3、不稳定 时间复杂度建堆O(n),堆调整O(nlogn),所以为O(nlogn) 空间复杂度O(1)


七、归并排序

1、基本思想:假设有两个有序的子文件,放在A[low......m],A[m+1......n]上,先将他们合并到一个Temp中,待排序完毕后在复制到原数组中。

2、代码(自顶向下)

//将两个子序列按照大小顺序填入临时数组temp中
void Merge(int arr[], int temp[], int start1, int end1, int end2)
{
	int start2 = end1 + 1;
	int tempindex = start1;
	int number = end2 - start1 + 1;
	while (start1<=end1 && start2<=end2)
	{
		if (arr[start1] <= arr[start2])
		{
			temp[tempindex++] = arr[start1];
			start1++;
		}
		else{
			temp[tempindex++] = arr[start2];
			start2++;
		}
	}

	while (start1 <= end1)
	{
		temp[tempindex++] = arr[start1];
		start1++;
	}

	while (start2<=end2)
	{
		temp[tempindex++] = arr[start2];
		start2++;
	}

	for (int i = 0; i < number; i++, end2--)
		arr[end2] = temp[end2];
}


void merge_sort(int arr[], int temp[], int start, int end)
{
	if (start >= end)
		return;

	int middle = (start + end) / 2;//分裂节点
	merge_sort(arr, temp, start, middle);//分别递归排序
	merge_sort(arr, temp, middle + 1, end);
	Merge(arr, temp, start, middle, end);//合并
}

/*归并排序*/
void MergeSort(int arr[], int length)
{
	int *temp = NULL;
	temp = new int[length];
	if (temp != NULL)
	{
		merge_sort(arr, temp, 0, length - 1);
		delete[] temp;
	}
}

3、稳定,时间复杂度O(nlogn) 空间复杂度O(n)


八、基数排序

1、基本思想:从低位到高位依次对数据进行排序,第d趟排序就是对第d位进行排序,所需箱子数就是技术rd。

2、代码

int find_max(int arr[], int length)//找到最大的一个数
{
	int max = arr[0];
	for (int i = 1; i < length; ++i)
	{
		if (arr[i]>max)
			max = arr[i];
	}
	return max;
}

int digitnumber(int number)//求数字的位数
{
	int num = 0;
	while (number > 0)
	{
		number = number / 10;
		num++;
	}
	return num;
}

int kdigitnumber(int number,int k)//求第k位的元素,从个位数开始计数
{
	number = number / pow(10, k);
	return number % 10;
}

/*基数排序*/
void RadixSort(int arr[], int length)
{
	int *temp[10];//指针数组,指向10个桶
	int max = find_max(arr,length);
	int maxDigit = digitnumber(max);
	int count[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };//每个桶元素的个数

	for (int i = 0; i < 10; ++i)//给桶分配空间,并初始化
	{
		temp[i] = new int[length];
		memset(temp[i], 0, sizeof(int)*length);
	}

	for (int i = 0; i < maxDigit; i++)
	{
		memset(count, 0, sizeof(int)* 10);
		for (int j = 0; j < length; j++)
		{
			int x = kdigitnumber(arr[j], i);
			temp[x][count[x]] = arr[j];
			count[x]++;
		}

		int index = 0;//对桶中的元素进行收集操作
		for (int k = 0; k < 10; k++)
		{
			for (int m = 0; m < count[k]; m++)
			{
				arr[index++] = temp[k][m];
			}
		}
	}
}

3、不稳定 时间复杂度O(kn)   空间复杂度O(n)(其中k为数字的最大位数)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值