chapter_sorting/insertion_sort/ #59
Replies: 43 comments 36 replies
-
发现一个小问题, |
Beta Was this translation helpful? Give feedback.
-
K神,插入排序的核心思想这么写会不会更容易理解和记忆呢:取未排序区间中的某个元素为基准数 |
Beta Was this translation helpful? Give feedback.
-
和斗地主,理扑克一个逻辑哦 |
Beta Was this translation helpful? Give feedback.
-
/**
* 希尔排序
* 是对插入排序的改进,插入排序,如果是5,3,,4,8,1这种最小数在很后面就会进行多次交换
* 希尔排序采用分组加插入排序处理这个问题,将长度/2为分组数量,每个分组在进行插入排序,
* 当步长为1的时候就是简单插入排序,不过此刻数据基本有序,只需要进行少量的交换
* @param ints 数组
* @param gap 组数
*/
public static void shellSort(int[] ints, int gap)
{
// 组数<1结束
if (gap < 1)
{
return;
}
// 有序判断,如果有序就直接结束
// if (isSorted(ints, 0, ints.length))
// {
// return;
// }
// 组数
gap /= 2;
// 步长
int step = gap;
// 对每一组进行排序,i表示每组首元素的下标
for (int i = 0; i < gap; i++)
{
// 对同一组的进行插入排序(和插入排序一样不过插入排序步长为1,这里步长会变)
// j表示同组的下标
for (int j = i + step; j < ints.length; j += step)
{
// 暂存有序区首位元素
int temp = ints[j];
int k = 0;
for (k = j - step; k >= 0; k -= step)
{
if (temp > ints[k])
{
break;
}
// 后移
ints[k + step] = ints[k];
}
// 插入
ints[k + step] = temp;
}
}
// System.out.println("分为" + gap + "组");
// System.out.println(Arrays.toString(ints));
// 递归
shellSort(ints, gap);
} |
Beta Was this translation helpful? Give feedback.
-
为什么我觉得插入排序和冒泡排序基本一样?冒泡排序需要一个tmp临时变量用于交换,插入排序也需要一个base变量。区别在于插入不是每一次都在交换,而是直到找到合适位置,但是我感觉这根本上没多大区别。另外元素“参与”排序的顺序不一样,一个头开始,一个从低开始。本质还是没区别么。。求人解答一下。 |
Beta Was this translation helpful? Give feedback.
-
三点改进:
一简化循环结构,条件放到内部,更易读;
二如果基准元素找到安置位置即跳出循环;
三如果基准元素就是安置位置,无需赋值操作;
public void insertionSort3(int [] array) {
// 外层循环 基准元素依次从左到右
for (int i = 0; i < array.length; i++) {
int base = array[i];
// 内层循环 依次从右到左,遍历已排序区间,查找基准元素合适安置位置
int j = i;
while (j > 0) {
if (array[j - 1] > base) {
// 前边元素依次赋值后续元素,实现移动效果
array[j]= array[j - 1];
} else {
// 如果基准元素已到达指定位置,无序继续比较下去。因为已排序区间为有序,第一个小于基准元素的话,该元素前边都小于基准元素。
break;
}
j --;
}
// 若已排序区间发生元素移动,才会赋值操作。
if (j != i) {
// j的区间为[0,i],不用考虑越界问题。由于break,此处j值对应上轮的array[j-1] 或array[0]。
array[j] = base;
}
}
} |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
😁说到扑克,我都喜欢拿到全部牌后再一张张摸,这样比直接全抓起来理的舒服点。 那么插入排序能不能直接另创一个数组,直接挨个元素往新数组加,加入新数组用二分查找,遇上值相同的直接插入,都不用考虑左右了。 |
Beta Was this translation helpful? Give feedback.
-
k神,感觉可以把希尔排序加上 |
Beta Was this translation helpful? Give feedback.
-
这里 java while语句里面,如果j=0,还会执行 j--么 |
Beta Was this translation helpful? Give feedback.
-
可以填一下 折半插入排序 希尔排序 |
Beta Was this translation helpful? Give feedback.
-
zig标准库的插入排序赋值有点多了,不知在zig标准库中可否改进? |
Beta Was this translation helpful? Give feedback.
-
function insertionSort(nums) {
for (let i = 1; i < nums.length; i++) {
let base = nums[i]
let j = i - 1
while (i >= 0 && nums[j] > base) {
// 交互位置
nums[j + 1] = nums[j]
nums[j] = base
j--
}
}
return nums
} 这样写应该还算插排,唯一差别就是将base和已排好的排比较,大的就交换位置 |
Beta Was this translation helpful? Give feedback.
-
请问大神,nums[j + 1] = base; 这一步不是很理解,他的作用是什么?可以删掉吗? |
Beta Was this translation helpful? Give feedback.
-
有点像打牌的时候抽一张放到手里牌正确位置的感觉 |
Beta Was this translation helpful? Give feedback.
-
虽然很像冒泡排序,但是一个天一个地,差别太大了。快几十倍都有可能 |
Beta Was this translation helpful? Give feedback.
-
小数据量最快的排序方式 |
Beta Was this translation helpful? Give feedback.
-
def sort(nums):
for i in range(1, len(nums)):
base = nums[i]
while i > 0 and base <= nums[i - 1]:
nums[i] = nums[i - 1]
i -= 1
nums[i] = base
return nums
sort([1,3,32,4,1,-100,23,17,23,6,-7,2,9,-1000]) |
Beta Was this translation helpful? Give feedback.
-
第二遍学习 自己写了个插排的算法 可以实现排序,但每进行一次循环就要赋一次值,相较于整体循环结束后再赋值显得低效 而且貌似还有优化的空间 |
Beta Was this translation helpful? Give feedback.
-
“冒泡排序基于元素交换实现,需要借助一个临时变量”这里说的临时变量是哪个啊 |
Beta Was this translation helpful? Give feedback.
-
def insertion_sort_with_binary(nums: list[int]):
nums = [1, 3, 32, 4, 1, -100, 23, 17, 23, 6, -7, 2, 9, -1000] |
Beta Was this translation helpful? Give feedback.
-
def shell_sort(nums: list[int]):
nums = [1, 3, 32, 4, 1, -100, 23, 17, 23, 6, -7, 2, 9, -1000] |
Beta Was this translation helpful? Give feedback.
-
个人理解插入和冒泡的区别在于中间变量的实际赋值发生位置是否在子循环内部,冒泡类似滑动窗口,而插入则是查询下标进行插入替换,所有具体优化思路也会不一样
|
Beta Was this translation helpful? Give feedback.
-
对于插入排序算法特性的部分有一点小疑问,每次插入操作应当分别需要循环1,2,...,n-1次?看描述是n-1,n-2,...,2,1次,似乎反过来了 |
Beta Was this translation helpful? Give feedback.
-
func InsertSort(nums []int) []int { |
Beta Was this translation helpful? Give feedback.
-
希尔排序算法def shell_sort(arr):
"""
使用自定义的插入排序逻辑,逐步缩小增量 gap,完成整个数组的排序。
"""
# 获取列表的长度
n = len(arr)
# 初始化增量 gap,初始值为数组长度的一半
gap = n // 2
# 循环到 gap 不能分割为止
while gap > 0:
# 对每个子序列进行插入排序
for i in range(gap, n):
# 记录下来要比较的数据
tmp = arr[i]
# 记录位置
j = i
# 判断是否要做插入排序,j >= gap 判断是否还有数据要比较,
# arr[j - gap] > tmp 判断是否满足插入排序条件
while j >= gap and arr[j - gap] > tmp:
arr[j] = arr[j - gap] # 将 arr[j - gap] 向右移动一位
j -= gap
arr[j] = tmp # 将 tmp 赋值到正确位置
# 缩小增量 gap
gap = gap // 2 |
Beta Was this translation helpful? Give feedback.
-
《算法 4》中给的递增函数是(3、- 1)/2,即 1,4,13,40,121,364... def shell_sort(nums):
"""
希尔排序算法
使用增量序列 (3^k - 1) / 2,即 h = 1, 4, 13, 40, 121, 364...
对每个子序列进行插入排序,逐步缩小 h,最终完成整个数组的排序。
"""
n = len(nums) # 获取数组长度
# 初始化增量 h,使用生成函数 (3^k - 1) / 2
h = 1
while h < n // 3: # 确保 h 的初始值足够大
h = 3 * h + 1 # 按照生成函数计算 h
# 主循环:逐渐缩小 h,直到 h = 1
while h >= 1:
# 对每个子序列进行插入排序
for sorted_index in range(h, n):
# 记录当前要插入的元素
tmp = nums[sorted_index]
# 从当前元素开始,向左遍历子序列
i = sorted_index
while i >= h and nums[i - h] > tmp:
# 将较大的元素向右移动
nums[i] = nums[i - h]
i -= h
# 将当前元素插入到正确位置
nums[i] = tmp
# 按照递增函数的规则,缩小 h
h //= 3 |
Beta Was this translation helpful? Give feedback.
-
这篇文章画演示更好理解:https://mp.weixin.qq.com/s/iJvPegXpBRI6dkzLWEE6dA |
Beta Was this translation helpful? Give feedback.
-
这篇文章动画演示更好理解:https://mp.weixin.qq.com/s/gpJgLEk1Ayxjw65_V-6jGg |
Beta Was this translation helpful? Give feedback.
-
day09 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
chapter_sorting/insertion_sort/
Your first book to learn Data Structure And Algorithm.
https://www.hello-algo.com/chapter_sorting/insertion_sort/
Beta Was this translation helpful? Give feedback.
All reactions