排序(大话数据结构阅读笔记)

排序的几种常见方法:

 定义一个顺序表结构 :

#define MAXSIZE 10000           //用于要排序数组个数最大值,可根据需要修改 
typedef struct
{
	int r[MAXSIZE+1];	//用于存储要排序数组,r[0]用作哨兵或临时变量
	int length;	        //用于记录顺序表的长度
}SqList;

1.简单排序

思路:让第一个位置元素都和它后面位置的元素逐个比较,如果大则交换,这样第一位置的元素在一次循环后一定变为最小值,然后让第二个位置的元素都和它后面位置的元素逐个比较,如果大则交换,这样出次最小值放到第二个位置,依次下去进行排序,如下图:

代码实现:

void BubbleSort0(SqList *L)
{
    int i,j;
    for(i=1;i<L->length;i++)        //有L->lenght个元素,要比较L->lenght次
    {
        for(j=i+1;j<=L->length;j++) //让第i个元素依次同它后面的元素比较,把最小值放到第i个位置
        {
            if(L->r[i]>L->r[j])     
                swap(L,i,j);
        }
    }
}
方法的优缺点 :优点是简单,缺点在排序好1和2的位置后,对其余关键字的排序没有什么帮助(数字3还被换到的最后一位),效率差.


2.冒泡排序法:

刚刚的简单排序是从第i个元素开始逐个与下面的元素比较,选出(length+1-i)个元素中的最小值放在第i个元素的位置.而冒泡排序的基本思想是两两比较相邻记录的元素,如果反序则交换,直到没有反序为止,第一次循环如下图:


代码实现:

void BubbleSort(SqList *L)
{
    int i,j;
    for(i=1;i<L->length;i++)            //比较L->length-1次
    {
        for(j=L->length-1;j>=i;j--)     //从下面的两个元素开始比较
        {
            if(L->r[j]>L->r[j+1])       //如果前者大于后者就交换(小的往上冒)
                swap(L,j,j+1);
        }
    }
}
优缺点:在不断循环过程中,除了将元素1放到第一个的位置,我们还将元素2从第九位置提高了第三位置,显然比简单排序进步,缺点这边固定循环Length-1次,如果在第
一次循环后已经有序,算法会依旧执行后面多余的Length-2次。

3.改进的冒泡排序

思想:设置一个标志,如果发现序列已经有序就退出循环.

代码实现:

void BubbleSort2(SqList *L)
{
    int i,j;
    Status flag=TRUE;
    for(i=1;i<L->length&&flag;i++)   //增加了标志,如果下面没有执行交换,就认为已经有序,for循环停止
    {
        flag = FALSE;               
        for(j=L->length-1;j>=i;j--)
        {
            if(L->r[j]>L->r[j+1])
            {
                swap(L,j,j+1);
                flag=TRUE;          //如果执行了交换,就将标志设置为TRUE
            }
        }
    }
}
4.选择排序

基本思想:将第一个元素逐个与后面的元素比较,记录下最小值的下标,将最小值与第一个元素交换,再将第二个元素逐个与后面的元素比较,记录下最小值的下标,将比较中的最小值与第二个元素交换,以此类推。

代码实现:

void SelectSort(SqList *L)
{
   int i,j,min;
   for(i=1;i<L->length;i++)            //比较L->length-1次
   {
       min = i;                         //min用来记录每一轮比较中最小值的下标
       for(j=i+1;j<=L->length;j++)
       {
           if(L->r[min]>L->r[j])
           {
               min = j;
           }
       }
       if(min!=i)                       //每一轮循环后,与将记录的最小值交换
            swap(L,i,min);
   }
}

5.归并排序

归并排序使用了分治的思想,要将一个数组排序,可以将它分为两半分别排序,然后将结果归并成一个排序好的数组。

//自顶向下的归并排序
class PaiXu
{
	static int[] aux;
	public static void sort(int[] a)
	{
		aux = new int[a.length];
		sort(a,0,a.length-1);
	}
	
	//分治的思想
	public static void sort(int[] a,int low,int high){
		if(low<high){
			int mid = (low+high)/2;
			sort(a,low,mid);				
			sort(a,mid+1,high);
			merge(a,low,mid,high);
		}
	}
	
	//merge函数将两个有序的数组,合并为一个有序的大数组
	public static void merge(int[] a,int low,int mid,int high){
		
		for(int i=low;i<=high;i++){
			aux[i] = a[i];
		}
	
		int i = low;
		int j = mid + 1;
		
		for(int k=low;k<=high;k++){			
			if(i>mid)				a[k] = aux[j++];
			else if(j>high)			        a[k] = aux[i++];
			else if(aux[i]>aux[j])	                a[k] = aux[j++];
			else 			  		a[k] = aux[i++];
		}
	}

	public static void main(String[] args)
	{
		int[] a= {90,50,10,90,30,70,40,10,80,60,20,10,70,37,5,2,1,9,43,23,11,44,1,1,90};
		sort(a);
		System.out.println(Arrays.toString(a));
	}	
}

快速排序:

	public void sort(int[] a)
	{
		int N = a.length-1;
		Qsort(a,0,N);
	}
	//典型的分治思想
	public void Qsort(int[] a,int low,int high)
	{
		
		if(low<high)
		{
			int pivot;
			pivot = Partition(a,low,high);
			Qsort(a,low,pivot-1);
			Qsort(a,pivot+1,high);
		}
	}
	
	public int Partition(int[] a,int low,int high){
		int i = low;
		int j = high;
		while(i<j){
			while(i<j&&a[j]>=a[low])
				j--;
			while(i<j&&a[i]<=a[low])
				i++;
			if(i>=j)		//最终是i==j停下来,这一点要记住
				break;
			exch1(a,i,j);
		}
		exch1(a,low,i);
		return j;
	}


优先队列:

许多应用需要处理有序的元素,但不一定要求它们全部有序,或是不一定要一次就将它们排序。很多情况下我们收集一些元素,处理当前最大的元素,然后在收集更多的元素,在处理当前最大的元素,然后在收集更多的元素,再处理当前的最大的元素。一种合适的数据结构支持这两种操作:删除最大的元素和插入元素

使用到的两个操作:

上浮:上浮指的是将大的结点上浮(插入元素时用到了上浮)

下沉:下沉指的是将大的结点小的下沉(删除元素时用到了下沉

两个都可以用来构建一个大顶堆。在优先队列中,对数组来说插入一个元素都是插入在数组尾部,此时使用上浮可以构建大顶堆。

优先队列的的操作的过程:

插入一个元素:向数组尾部插入一个元素,通过上浮将大的值上浮到堆顶,构建大顶堆

删除一个元素:将第一个元素取出放到临时变量中(这是这堆数中最大的一个数),然后将第一个元素和最后一个元素交换,并将最后一个数的位置设置为null即删除最后一个元素,此时第一个元素并不是最大值,也就是说现在构成的堆也不是大顶堆,此时对第一个元素进行下沉操作,通过下沉构建大顶堆

记忆中用到的地方:阻塞队列中,PriprityBlockingQueue中用到。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值