数据结构学习笔记 —— 排序

井然有序是最高效的。
直接插入排序、希尔排序、选择排序、冒泡排序、位排序、快速排序
1. 直接插入排序

(1) 思想:假设序列n分为两个部分,有序k和无序(n-k)。排序过程中,每次从无序的部分中取出第一个元素,将它插入到有序表中适当的位置,使之有序。
(2) 时间复杂度:最坏O(n2),最好O(n),平均O(n2)。
(3) 空间复杂度:O(1)。
(4) 对于小规模数组和基本有序的数据而言,直接插入排序比较高效。
(5) 关键代码:先在有序区间array[0] …array[k-1]区间给array[k]找到插入的位置;然后将比array[k]大的数据向后移动一个位置。(移动,插入)

for(k = 1; k < n; k++)
{
    for( j = k-1; j > 0; j--)
    {
        if(array[j] < array[i])
        {
            break;
        }
   }
   
   if( j != k-1)
   {
      temp = array[k];
      for(m = k; m > j+1; m--)
      {
          array[m] = array[m-1];
       }
       array[j+1] = temp;
  }
}
2. 希尔排序

(1) 思想:把较大的数据集合按数组下标的一定增量gap进行分组,然后对每组使用直接插入排序。
(2) 增量的选择
(3)关键代码:

for(gap = N/2; gap > 0; gap = gap/2)
{
    for(i = gap; i < N; i++)
    {
        int temp = arr[i];
        for(j = i - gap; (j>= 0) && (temp < array[j]; j = j -gap)
        {
            array[j+gap] = array[j];
        }
array[j+gap] = temp;
    }
}
3. 选择排序

(1) 思想:假设序列n分为两个部分,有序k和无序(n-k)。排序过程中,每次从无序的部分中,将最大或者最小的元素取出,将它放到有序的末尾。
(2) 时间复杂度:O(n2)。
(3)关键代码:

    for(i = 0; i < n; i++)
    {
        min=i;
        for(j = i+1; j < n;  j++)
        {
            if(array[j] < array[min])
            {
                min = j;
             }
        }
        
        if(min != i)
        {
            temp = array[i];
            array[i] = array[min];
            array[min] = temp;
        }
    }
4. 冒泡排序

(1) 思想:冒泡,冒泡,以从小到大排序为例说明,依次比较前后两个数,若前面的数大于后面的数,则交换两者的位置。这样,逐个选出最大的,次大的…
(2)时间复杂度:O(n2)。
(3)关键代码:

for(k = n-1; k > 0; k--)
{
   int flag = 0;  //优化的冒泡,置一个标志位。若某一趟排序没有发生交换,则说明已经是有序的。
    for( l = 0; l < k; l++)
    {
        if(array[l] > array[l+1])
        {
            flag = 1;
            temp = array[l];
            array[l] = array[l+1];
            array[l+1] = temp;
         }
      }
     if(0 == flag)
     {
         break;
     }
  }

5. 位图排序

(1) 数据特点:无重复数据、最大值已知、整型。
(2) 思想:用一个bit位标识一个int 整数是否出现。若该位为1,则出现;若该位为0,则未出现。

  • 假设有N个未重复的整数,最大值不大于N。
LENGTH = N/32 + 1;
int bitArray[LENGTH] = {0};

for(i = 0; i < N; i++)
{
    int k = i/32;
    int l  = i%32 + 1;
   
   //将bitArray[k]的第l位置为1。
  bitArray[k] = bitArray[k] | (1 << l) ;
}
 
//输出位排序后的数据
for(i = 0; i < LENGTH;i++)
{
     for(j = 0; j< 32; j++)
     {
         if((bitArray[i] & (1 << j))
         {
             temp = i * 32 + j;
             printf("%d", &temp);
          }
     }

6. 快速排序

(1) 思想:分而治之。以从小到大排序为例说明。

  • 选一个基数。
  • 小于基数的往左边扔,大于基数的往右边扔。
  • 然后针对基数左右两边的数,重复上述两个步骤,直到往左右两边扔的数只有一个或0个为止。
  • 递归。

(2) 关键代码:

void quicksort(int left, int right) {
	int i, j, temp, base;
	
	if(left > right)
	{
		return;
	}
    base = array[left];    
    i = left;
    j = right;
    while(i != j)
     { 
    	while(a[j] >= base && i < j)
    	{
    		j--;
        }
    	while(a[i] <= base && i < j)
    	{
    		i++;  
        }     
    	if(i < j)  //交换两个数在数组中的位置
    	{
    		temp = a[i];
    		a[i] = a[j];
    		a[j] = temp;
    	}
    }
    //最终将基准数归位
    a[left] = a[i];
    a[i] = base;
    quicksort(left, i-1);
    quicksort(i+1, right);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值