基础数据结构——直接插入排序和希尔排序——自用笔记
2023-09-27 14:29:25 时间
直接插入排序
原理
每次从待排序队列中取一个值,放到已排序好的队列,再次保持有序,重复这样的动作,直到把待排序队列中的值全部取完。
其实和玩扑克牌一样;
比如你揭的几张牌是顺子,但到底是不是,你要给他们排个序
示例:
第二次揭牌结果:
继续揭牌:
结果:
按照这样的方式,最终结果为:
代码实现(C语言)
void Insert_Sort(int* arr, int len)
{
assert(arr != NULL);
int tmp = 0;
int i = 0, j = 0;
for (i = 1; i < len; ++i)
{
tmp = arr[i];
for (j = i - 1; j >= 0; --j)
{
if (arr[j] > tmp)
{
arr[j + 1] = arr[j];
}
else
{
break;
}
}
arr[j + 1] = tmp;
}
}
运行示例:
void Show(const int* arr, int len)
{
assert(arr != NULL);
for (int i = 0; i < len; ++i)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main(void)
{
int ar[] = { 9,6,5,4,2,3,1,7,8,0 };
int len = sizeof(ar) / sizeof(ar[0]);
Show(ar, len);
Insert_Sort(ar, len);
Show(ar, len);
return 0;
}
运行结果:
评价
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性: 稳定的
适用场景
- 当问题规模很小时(n很小),则 n^ 2不会很大。
- 待排序队列越有序,越优解。
希尔排序
原理
希尔排序是D.L.Shell在对直接插入排序改进后的算法。
采取跳跃分割的策略: 将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。 即缩小增量。
增量要求:
- 增量一般是以{ 5, 3, 1}来分。
- 一定以一结尾。
- 尽可能互素。
图示
以五为增量给数据分组
然后每组按照直接插入排序的方法来排序。
第一组:
按照直接插入排序,把13保存到tmp中,往前比较,13比6大,就把tmp放到6后面;再把12保存到tmp中,往前比较,比13小,就把13往后覆盖,再和前面6比较,比6大,则放到6的后面。。。。
这时候数据变成了:
第二组:
原始数据变为:
以此方法,把图示的五组数据进行直接插入排序后,得到的结果为:
以3为增量给数据分组:
也是按照直接插入排序来做:
以此类推,最终数据为:
可以看出,相较于初始数据,经过两次缩小增量排序后,数据变得比较有序了,再执行最后一次,以 1 为增量,就是执行一遍直接插入排序,因为数据比较有序,所以交换次数会少很多。
以1为增量结果:
这样就完全有序了
代码实现(C语言)
static void Shell(int* arr, int len, int gap)
{
int tmp;
int i = 0, j = 0;
for (int i = gap; i < len; i++)//每次从待排序队列中取的值
{
tmp = arr[i];//用tmp保存待插入的值
for (j = i - gap; j >= 0; j = j - gap)//从右向左找不比tmp大的值
{
if (arr[j] > tmp)//如果比tmp大 则向右放一格
{
arr[j + gap] = arr[j];
}
else//如果不比tmp大
{
break;
}
}
arr[j + gap] = tmp;
}
}
void ShellSort(int* arr, int len)
{
assert(arr != NULL);
int gap[] = { 5, 3, 1 };
int lengap = sizeof(gap) / sizeof(gap[0]);
for (int i = 0; i < lengap; i++)
{
Shell(arr, len, gap[i]);//5 3 1
}
}
示例:
void Show(int* ar, int len)
{
for (int i = 0; i < len; ++i)
{
printf("%d ", ar[i]);
}
printf("\n");
}
int main(void)
{
int ar[] = { 3, 6, 14, 9, 11, 8, 5, 2, 13, 15, 1, 7, 4, 12, 10 };
int len = sizeof(ar) / sizeof(ar[0]);
Shell_Sort(ar, len);
Show(ar, len);
return 0;
}
运行结果:
评价
- 希尔排序的时间复杂度为O (N^ 1.3~1.5)。
- 空间复杂度为 0(1)。
- 稳定性: 不稳定。
相关文章
- 【剑道】 剑道基础 剑道入门 学习笔记
- 从AI顶会最佳论文,看深度学习的理论基础
- [ kvm ] 学习笔记 2:虚拟化基础
- Google Guava学习笔记——基础工具类Preconditions类的使用
- C#基础笔记
- [转]C++学习–基础篇(书籍推荐及分享)
- Vue.js:Webpack基础入门学习笔记
- Web前端学习笔记之jQuery基础
- Python Web学习笔记之Python多线程基础
- Angular 学习笔记 (cdk focus monitor 和一些 focus tabindex 的基础)
- 【Hive】Hive 安装&使用基础
- Linux操作系统基础(完结)
- C++学习笔记_01基础 2021-04-15
- go语言设计与实现-语言基础-阅读笔记
- 【笔记】JavaScript版数据结构与算法——基础算法之“递归类”(93. 复原IP地址)
- 【笔记】JavaScript版数据结构与算法——基础算法之“排序类”(922. 按奇偶排序数组 II)
- 【笔记】JavaScript版数据结构与算法——基础算法之“排序类”(164. 最大间距)
- 【笔记】JavaScript版数据结构与算法——基础算法之“正则类”(10. 正则表达式匹配)
- 汇编语言笔记(一)——汇编语言基础
- solidworks基础-装配那些事
- 8.div+css基础学习三 列表和超链接伪类
- 大数据必学Java基础(四十):面向对象三大特性之一继承(Inheritance)
- 李洪强iOS开发之【零基础学习iOS开发】【02-C语言】02-第一个C语言程序
- 基础数据结构——简单选择排序和堆排序——笔记自用