小白学习排序的记录
(三)选则排序
1.简单选则排序
(1)中心代码:二重循环。
(2)具体实现:数组存储,定义一个存最小下标的整数min_index,将数组中的每一个数与所有数依次比较,只要后面的数比第一个数小就把在其下标存在min_index中。内层循环结束一次,找到一个此时最小的数的下标,它存在min_index中,找到后在内层循环外部,将最小值存入此时的i下标位置。(i表示在数组中的几号位)依次找到第几小的数。
代码
代码
void sort(int *nums, int size)
{
for(int i=0;i<size;i++)
{
int min_index=i;
for(int j=i+1;j<size;j++)
{
if(nums[j]<nums[min_index])
{
min_index=j;
}
}
int temp=nums[i];
nums[i]=nums[min_index];
nums[min_index]=temp;
}
}
PS:时间复杂度是O(n*n),空间复杂度是O(1)
2.堆排序
note:其实堆就是把一群数字想象成一个三角堆,就是完全二叉树,有小根堆,大根堆,小根堆就是父节点小于左右孩子,大根堆就是父节点大于左右孩子。
(1)中心代码:循环
(2)具体实现:
1..定义:用数组来存储树,在想象中,数组的下标依次代表其在树中的位置如图
数组下标是从0开始的,已知某一数的下标(i),就可求得其孩子的下标,左孩子为2*i+1,右孩子为2*i+2。
2..实现:一个函数sort用来排小根堆,其实现思路为:给入一个需要排的parent node(leaf nodes 不需要排,没孩子),要父亲和左右孩子中最小的数来做新父亲(parent node),先比较孩子中谁最小,再将最小的孩子与旧父亲比较谁更小,谁小谁做新父亲。注意选取第一个父亲时,选下标最大的那个parent node,计算方法,假如一个完全二叉树中有n个结点,最小的,也就是序号最大的那个父亲,为n/2,由于数组从0开始,其在数组中对应的下标为n/2-1。
在main函数中需要不断的调用sort函数排需要排的父亲,直到下标=0时停止循环。
note:排好的数组并不是完全有序的,只能最简便的找到0号位置的数是最大的或是最小的。
代码解释
总代码
#include<stdio.h>
#define N 4
void getsnums(int *nums, int n)
{
printf("请输入4个数\n");
for(int i=0;i<n;i++)
{
scanf("%d", &nums[i]);
}
}
void shownums(int *nums, int n)
{
for(int i=0;i<n;i++)
{
printf("%d ", nums[i]);
}
}
void sort(int *nums, int n, int m)//堆小根堆的函数
{
int data=nums[m];
for(int j=2*m+1;j<=n;j=j*2+1)
{
if(j<n-1&&nums[j]>nums[j+1])j++;
if(data<=nums[j])break;
nums[m]=nums[j];
m=j;
}
nums[m]=data;
}
int main()
{
int f[N];
getsnums(f, N);//输入树
for(int i=N/2-1;i>=0;i--)
{
sort(f, N, i);
}
shownums(f, N);
return 0;
}
PS:时间复杂度为O(nlogn),空间复杂度为O(n*n)
理解了思想也可以用其他的数据结构实现,可以是链表,就是麻烦。