0
点赞
收藏
分享

微信扫一扫

(端午特别版)【C语言 - 数据结构】排序(上)

蓝莲听雨 2022-06-05 阅读 56

我在这里祝大家端午节快乐!

文章目录

  • 一、排序的概念及其运用 
  • 二、常见的排序算法及其实现
    • 冒泡排序
    • 插入排序
    • 堆排序
    • 选择排序
    • 希尔排序
  • 三、排序算法复杂度及稳定性分析
  • 总结
    提示:以下是本篇文章正文内容,下面案例可供参考

 一、排序的概念及其运用

1.1排序的概念

啥是稳定性,稳定性的概念:

内部排序和外部排序的概念:

对于内排序来说,排序算法的性能主要是受三个方面影响:

1.2常见的排序算法


二、常见的排序算法及其实现

2.1冒泡排序

我想大家都对冒泡排序不陌生,毕竟这是许多初学者最开始学的一种排序算法,今天让我们剖析一些这个算法吧!  

 

冒泡排序的代码:

void BubbleSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int exchange = 0;//定义一个变量判断是否发生了交换,若没有交换则直接break出去
		for (int j = 0; j < n - i - 1; j++)
		{
			if (a[j] > a[j + 1])
			{
				exchange = 1;
				Swap(&a[j], &a[j + 1]);
			}
		}
		if (exchange == 0)//说明没有交换过
		{
			break;
		}
	}
}

如果是用C语言写的代码建议大家写一个Swap函数和PrintfArray输出数组的函数

Swap和PrintfArray函数代码:

void Swap(int* pa, int* pb)
{
	int tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
void PrintfArray(int* a, int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

 2.2插入排序

2.2.1插入排序的基本思想 

2.2.2插入排序的操作:

 2.2.3直接插入排序的特性总结:

插入排序代码:

void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		//[0, end] end + 1
		int end = i;
		//单趟排序; [0, end] 有序的。 end + 1位置的值,插入进入,保持他依旧有序

		int tmp = a[end + 1];

		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];//先交换
				--end;//往前
			}
			else
			{
				break;
			}
			a[end + 1] = tmp;//tmp的值改到了之前的end位置
		}
	}
	
}

 冒泡排序和插入排序对比:

 2.3堆排序

书中的描述:

代码示例:(小根堆)

void AdjustDown(HPDataType* a, size_t size, size_t root)
{
       size_t parent = root;
       size_t child = parent * 2 + 1;//默认是左孩子
       while (child < size)
       {
              //1、选出左右孩子中小的那个,而且保证不会越界访问
              if (child + 1 < size && a[child + 1] <a[child])//建大堆时< 改 >
              {
                      ++child;//左孩子变为右孩子
              }
              if (a[child] < a[parent])//建大堆时< 改 >
              {
                      Swap(&a[child], &a[parent]);
                      parent = child;//继续计算
                      child = parent * 2 + 1;//默认还是计算左孩子
              }
              else
              {
                      break;
              }
       }
}
void HeapSort2(int* a, int n)
{
	//向上调整--建堆
	//for (int i = 1; i < n; ++i)
	//{
	//	AdjustUp(a, i);
	//}
	//向下调整--建堆O(N)
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDown(a, n, i);//为什么向下调整要多传一个参数,因为当child>=size 时说明已经到了边界
	}
	size_t end = n - 1;//n - 1是最后一个数据的下标
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		//次大的数到了倒数第二个位置
		--end;
	}
}
int main()
{
//	TestHeap();
	int a[] = { 4 , 2, 7, 8, 5, 1, 0, 6 };
	HeapSort(a, sizeof(a) / sizeof(int));
	for (int i = 0; i < sizeof(a) / sizeof(int); i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
	return 0;
}

 2.4选择排序 

 2.4.1基本思想:

2.4.2直接选择排序:

2.4.3直接选择排序的特性总结:

选择排序与堆排序对比:

选择排序的代码:

思路:每一次选出最大最小值,最大放最后,最小放后面,再left++,right--缩小区间

void SelectSort(int* a, int n)
{
    int left = 0, right = n - 1;
    while (left < right)
    {
        int mini = left, maxi = left;
        for (int i = left + 1; i <= right; i++)
        {
            if (a[i] < a[mini])
            {
                mini = i;
            }
            if (a[i] > a[maxi])
            {
                maxi = i;
            }
        }
        Swap(&a[left], &a[mini]);
        //maxi可能与left重叠
        if (left == maxi)
        {
            maxi = mini;
        }

        Swap(&a[right], &a[maxi]);
        left++;
        right--;
    }
    
}

  2.5希尔排序

   希尔排序我们可以简单理解成是插入排序加强版,而且是史诗级加强。

2.5.1希尔排序的原理:

 2.5.2希尔排序的特性总结:

希尔排序代码:

void ShellSort(int* a, int n)
{
    //预排序
    int gap = n;
    while (gap > 1)
    {
        gap = gap / 3 + 1;
        for (int i = 0; i < n - gap; i += gap)//为什么是到n - gap因为
        //结束前最后一次执行的下标是n - gap - 1
        {
            int end = i;
            int tmp = a[end + gap];
            while (end >= 0)
            {
                if (tmp < a[end])
                {
                    a[end + gap] = a[end];
                    end -= gap;
                }
                else
                {
                    break;
                }
                a[end + gap] = tmp;
            }
        }
    }
    
    
}


 三、排序算法复杂度及稳定性分析

3.1算法的空间特征

3.2算法与数据结构的关系

3.3算法的分类:

3.4算法的稳定性:

  数据量为1万时插入、希尔、和冒泡算法的时间:

  数据量为10万时插入、希尔、和冒泡算法的时间: 

数据量为1000万时算法的时间(只比较堆排序和希尔排序)

 


总结 

        

         本文约有5000字,从排序的概念及运用,和常见的排序算法及其实现,排序算法复杂度及稳定性分析三大点为大家简要分析总结了一下简单排序,希望每一位读者读后都能对排序有更深的理解,都能够有所收获!

举报

相关推荐

0 条评论