数据结构排序——选择排序与堆排序(c语言实现)

简介: 数据结构排序——选择排序与堆排序(c语言实现)

1.选择排序



1.1基本介绍


选择排序(Selection Sort):是一种简单直观的排序算法.它的基本思想是在未排序序列中找到最小(大)的元素,放到序列的起始位置,然后再从剩余未排序元素中找到最小(大)的元素,放到已排序序列的末尾。重复这个过程,直到所有元素都排好序。


选择排序的特性:


直接选择排序思考非常好理解,但是效率不是很好,所以很少使用

时间复杂度:O(N^2)

空间复杂度:O(1)

稳定性:不稳定


1.2代码实现


1.2.1基础款


void Swap(int* x, int* y)
{
  int tmp = *x;
  *x = *y;
  *y = tmp;
}
void SelectSort(int* a, int n)//升序
{
  for (int i = 0; i < n-1; i++)//n个数据,排n-1次
  {
    int mini = i;//0到i-1都已经排好,下一个就放在i这个位置上
    for (int j = i+1; j < n; j++)//从i到n-1找最小的,因为本身是i,所以j可以中i+1开始
    {
      if (a[minf] > a[j])
      {
        minf = j;//找到小的就来替换
      }
    }
    Swap(&a[minf], &a[i]);
  }
}
int main()
{
  int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };
  printf("排序前:");
  for (int i = 0; i < sizeof(a) / sizeof(int); i++)
  {
    printf("%d ", a[i]);
  }
  printf("\n");
  SelectSort(a, sizeof(a) / sizeof(int));
  printf("排序后:");
  for (int i = 0; i < sizeof(a) / sizeof(int); i++)
  {
    printf("%d ", a[i]);
  }
  printf("\n");
  return 0;
}


1.2.2进阶款


之前都是一次选一个最小的放在左侧。现在一次选出最大和最小,分别放在左侧和右侧

void SelectSort(int* a, int n)//升序
{
  int begin = 0, end = n - 1;
  while (begin < end) //begin=end时就已经排好了
  {
    int mini = begin, maxi = begin;//不知道会指向哪里,所以要每次都初始化
    for (int i = begin + 1; i <= end; i++)//从begin到end找最大和最小
    {
      if (a[i] < a[mini])
      {
        mini = i;
      }
      if (a[i] > a[maxi])
      {
        maxi = i;
      }
    }
    Swap(&a[begin], &a[mini]);//最小跟begin换
    if (begin == maxi)//有可能begin位置就是此时最大的,maxi=begin,要是交换了,maxi值就不对了
    {
      maxi = mini;//让maxi仍是最大的数据的索引(此时数据被换到mini所指)
    }
    Swap(&a[end], &a[maxi]);
    begin++;
    end--;
  }
}


2.堆排序


2.1基本介绍


之前在堆应用这篇文章我已经讲过了堆排序和TOP-K问题


那这次就再次大致讲解一下


如果是升序,就建立大堆;是降序就建立小堆。


因为思路是(以升序为例):大堆的堆顶一定是最大的,我们就把堆顶与堆尾交换后,除去最后一个对新堆顶进行向下调整。完成后,堆顶与倒数第二个交换…


2.2代码实现


#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
void Swap(HPDataType* p1, HPDataType* p2)
{
  HPDataType tmp = *p1;
  *p1 = *p2;
  *p2 = tmp;
}
void AdjustUp(HPDataType* a, int child)
{
  int father = (child - 1) / 2;
  while (child > 0)
  {
    if (a[child] > a[father])
    {
      Swap(&a[child], &a[father]);
      //更新下标
      child = father;
      father = (father - 1) / 2;
    }
    else
    {
      break;//一旦符合小堆了,就直接退出
    }
  }
}
void AdjustDown(HPDataType* a, int n, int father)
{
  int child = father * 2 + 1;//假设左孩子大
  while (child < n)
  {
    if (child + 1 < n && a[child] < a[child + 1])
    {
      child++;
    }
    if (a[child] > a[father])
    {
      Swap(&a[child], &a[father]);
      father = child;
      child = father * 2 + 1;
    }
    else
    {
      break;
    }
  }
}
void HeapSort(int* arr, int n)//升序
{
  //先建大堆
  for (int i = 0; i < n; i++)
  {
    AdjustUp(arr, i);
  }
  int a = n - 1;
  while (a > 0)
  {
    //此时最大的是堆顶,堆顶跟最后一个交换
    Swap(&arr[0], &arr[a]);
    //现在最大的已经在最后了,不考虑它,把新塔顶降下来,重新编程大堆
    AdjustDown(arr, a, 0);
    a--;
  }
}
int main()
{
  int arr[]= { 4,6,2,1,5,8,2,9 };
  for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
  HeapSort(arr, sizeof(arr) / sizeof(int));
  for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
  {
    printf("%d ", arr[i]);
  }
}

这次就到这里啦,感谢大家支持!!!

目录
相关文章
|
22天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
104 9
|
21天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
60 16
|
16天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
63 8
|
16天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
54 7
|
21天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
72 8
|
23天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
50 4
|
25天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
56 3
|
23天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
40 0
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
35 3
|
Linux C语言
Linux下编写选择排序(C语言)
1、创建源文件。 vi bubble.c 2、编写源代码 2、执行命令:gcc bubble.c -Wall -o app    (其中的-Wall标识严格编译) 3、执行命令:./app 
883 0