排序算法

冒泡排序:

思想:从左端开始两个数两个数的(相邻的两个数)开始进行比较,第一次先求出n个数中最小的数,放在下标为1的位置。爹日次开始从下标为2的位置来时,也是两个数(相邻的两个数开始比较)。比较出n-1个数里面最小的那个数放在下表是2的位置哪里。一次类推。

for(int i=0 ; i<num.length ; i++){
            for(int j=0 ; j<num.length-i-1 ; j++){
                if(num[j]>num[j+1]){
                    int temp = num[j];
                    num[j] = num[j+1];
                    num[j+1] = temp;
                }
            }
        }

选择性排序:

思想:先找出数列的最小值,将这个所在的元素位置和第一个数相交换,如果最小值本来就在最左端了那就不用操作了。然后从第二个位置开始,再找出最小值和第二个数相交换。以此类推(记住是交换不是直接赋值)

int a[]= {3,4,2,6,4,11,8,7};
    for (int i=0; i<8-1; i++)
    {
        int flag=i;
        for (int j=i+1; j<8; j++)
        {
            if (a[j] < a[flag])
            {
                flag=j;
            }
        }
        int temp = a[flag];
        a[flag] = a[i];
        a[i] = temp;
    }

插入排序

直接插入排序的思想是,把一个无序的数组插入到有序的数组里面就会产生一个有序的数组,那么为了空间的合理利用,以及复杂度,所以不会单独开一块数组空间,而是把本数组的第一个数看作一个有序数组。所以这就有了下面的话。

思想:(直接插入排序)插入排序先第一步固定左边第一个数(已操作的数),然后从第二个数(未操作的数)开始和已经操作的数比较要是小的话(第二个数也变为已操作的数了),就互换位置。然后第三个数开始继续和已操作的数比较,一个一个的向前比较,直到遇见比自己小的数就停下来。以此类推。

 int a[]={3,4,2,6,4,11,8,7};
    for(int i=1;i<8;i++)
    {
        for(int j=0;j<i;j++)
        {
            if(a[i]<a[j])
            {
                int temp=a[j];
                a[j]=a[i];
                a[i]=temp;
            }
        }
    }

堆排序:

思想:(这里只讲排序不讲堆)首先前提条件是:1.完全二叉树。2.父亲节点要大于子节点(大顶堆,小顶堆的话就是反过来的)。二叉树可以用数组来维护,所以堆也是 如此。然后堆的操作是这样的:如果父亲节点和子节点相比较的话,要是小的话那就要交换。(要是两个子节点都比父节点要来的大的话,那和谁交换呢)和最大的子节点交换。ddd=大顶堆

void ddd(int arr[],int i,int size){
	if(i<size){
		int left=2*i+1;
		int right=2*i+2;
		int largest=i;
		if(left<size){
			if(arr[largest]<arr[left]){
				largest=left;
			}
		}
		if(right<size){
			if(arr[largest]<arr[right]){
				largest=right;
			}
		}
		if(largest!=i){
			int temp=arr[largest];
			arr[largest]=arr[i];
			arr[i]=temp;
			ddd(arr,largest,size);
		}
	}
}

归并排序:

思想:这里用的递归方法。首先归并排序和归并操作脱不了干系。先将当前的数组分成两个数组,然后将两个排好顺序的数组合并为一个序列。(口笨,不知道怎么表达)这就是归并排序了。直接上代码

void merge(int arr[], int left, int mid, int right)
{
	int n1 = mid - left + 1;	//leftPart数组的长度;  [left,mid]
	int n2 = right - mid;		//rightPart数组的长度  [mid+1,right];
	
	int *leftPart = new int[n1];
	int *rightPart = new int[n2];
	
	//复制到左右两边
	for(int i = 0; i < n1; i++)
	{
		leftPart[i] = arr[left + i];
	}
	for(int i = 0; i < n2; i++)
	{
		rightPart[i] = arr[mid + i + 1]; //mid在左边 
	}
	
	//左右两部分合并 
	int i = 0, j = 0, k = left;
	while(i < n1 && j < n2)
	{
		if(leftPart[i] <= rightPart[j])
		{
			arr[k++] = leftPart[i++];
		}
		else
		{
			arr[k++] = rightPart[j++];
		} 	 
	}
	while(i < n1)
	{
		arr[k++] = leftPart[i++];
	}
	while(j < n2)
	{
		arr[k++] = rightPart[j++];
	}
	delete [] leftPart;
	delete [] rightPart;	 
} 
void mergeSort(int arr[],int left, int right)
{
	if(left < right)
	{
		int mid = left + ((right - left)>>1);
		
		mergeSort(arr, left, mid);
		mergeSort(arr, mid + 1, right);
		
		merge(arr, left, mid, right);
	}
}

快排:

快排至少有三种以上的写法,这里我讲左右指针法,区别在于我交换的是左右指针的位置,而不是和基准数的位置(挖坑法)

思想:举个例子,有这么一个数组:6,1,2,7,9,3,4,5,10,8。那么现在我要对这个数组利用快排进行排序,使得数组是有序的。

  根据快排的思想,首先要找到一个基准数,我们一般用第一个数作为基准数,那么现在再设立左边和右边的两个指针,首先i指向6,j指向8。

那么现在j指针开始向右边移动,这时候j指针要去找比6小的数(5),找到之后呢,i开始向左边移动,找大于基准数的数(7),找到之后i,j位置上的数相交换(和挖坑不一样)。这时候数据变为:6,1,2,5,9,3,4,7,10,8。以此类推一直找下去之后当i,j碰到一起的时候,把i,j共同位置上面的数据和基准数据做一个交换,所以最后的数据是这样子的:3,1,2,5,4,6,9,7,10,8

所以呢,这时候我们就达到目的了,比基准数小的都在左边,比基准数大的都在右边。

那么现在继续,再左边的区间里面其实数据还是混乱的,那么就再左边的区间里面再一次实现第一次的比较

(3,1,2,5,4)。右边也一样,一次类推一直校验下去(所以是会用到递归的)

上代码:

#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left, int right) {
	int i, j, t, temp;
	if(left > right)
		return;
    temp = a[left]; //temp中存的就是基准数
    i = left;
    j = right;
    while(i != j) { //顺序很重要,要先从右边开始找
    	while(a[j] >= temp && i < j)
    		j--;
    	while(a[i] <= temp && i < j)//再找右边的
    		i++;       
    	if(i < j)//交换两个数在数组中的位置
    	{
    		t = a[i];
    		a[i] = a[j];
    		a[j] = t;
    	}
    }
    //最终将基准数归位
    a[left] = a[i];
    a[i] = temp;
    quicksort(left, i-1);//继续处理左边的,这里是一个递归的过程
    quicksort(i+1, right);//继续处理右边的 ,这里是一个递归的过程
}
int main() {
	int i;
    //读入数据
	scanf("%d", &n);
	for(i = 1; i <= n; i++)
		scanf("%d", &a[i]);
    quicksort(1, n); //快速排序调用
    //输出排序后的结果
    for(i = 1; i < n; i++)
    	printf("%d ", a[i]);
    printf("%d\n", a[n]);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值