数据结构 | 动画表示八大排序算法,一看就懂
yuyutoo 2024-10-12 01:08 6 浏览 0 评论
一、直接插入排序
基本思想:
我们平时玩扑克牌时,摸牌阶段的排序就用到了插入排序的思想
- 1、当插入第n个元素时,前面的n-1个数已经有序
- 2、用这第n个数与前面的n-1个数比较,找到要插入的位置,将其插入(原来位置上的数不会被覆盖,因为提前保存了)
- 3、原来位置上的数据,依次后移
具体实现:
- ①单趟的实现(将x插入到 [0,end] 的有序区间)
即一般情况下的插入,我们随机列举了一些数字,待插入的数字分为两种情况
(1)待插入的数字是在前面有序数字的中间数,直接比较将x赋值给end+1位置 (2)x是最小的一个数,end就会到达-1的位置,最后直接将x赋值给end+1位置
- ②整个数组排序的实现
我们一开始并不知道数组是不是有序的,所以我们控制下标,end从0开始,将end+1位置的值始终保存到x中,循环进行单趟排序即可,最后结束时end=n-2,n-1位置的数字保存到x中
总体代码:
void InsertSort(int* a, int n)
{
assert(a);
for (int i = 0; i < n - 1; ++i)
{
int end = i;
int x=a[end+1];//将end后面的值保存到x里面了
//将x插入到[0,end]的有序区间
while (end >= 0)
{
if (a[end] > x)
{
a[end + 1] = a[end]; //往后挪动一位
--end;
}
else
{
break;
}
}
a[end + 1] = x; //x放的位置都是end的后一个位置
}
}
直接插入排序总结:
- ①元素越接近有序,直接插入排序的效率越高
- ②时间复杂度:O(N^2)
最坏的情况下,每次插入一个数字,前面的数字都要挪动一下,一共需要挪动1+2+3+……+n=n(n+1)/2
③空间复杂度:O(1)
没有借助额外的空间,只用到常数个变量
二、希尔排序
基本思想:
- 1、先选定个小于n的数字作为gap,所有距离为gap的数分为一组进行预排序(直接插入排序)
- 2、再选一个小于gap的数,重复①的操作
- 3、当gap=1时,相当于整个数组就是一组,再进行一次插入排序即可整体有序
例如:
具体实现:
①单组排序
和前面的直接插入相同,就是把原来的间隔为1,现在变为gap了,每组分别进行预排序
②多组进行排序
③整个数组进行排序(控制gap)
多次预排序(gap>1)+ 一次插入排序(gap==1)
(1)gap越大,预排越快,越不接近于有序
(2)gap越小,预排越慢,越接近有序
结果就是:
总体代码:
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 1)
{
gap /= 2;
for (int i = 0; i < n - gap; i++)
{
int end = i;
int x = a[end + gap];
while (end >= 0)
{
if (a[end] > x)
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = x;
}
}
}
希尔排序总结:
- ①希尔排序是对直接插入排序的优化
- ②时间复杂度:O(N^1.3)
- ③空间复杂度:O(1)
三、选择排序
基本思想:
每次从数组中选出最大的或者最小的,存放在数组的最右边或者最左边,直到全部有序
具体实现:
我们这里进行了优化,一次排序中,直接同时选出最大的数(a[maxi])和最小的数(a[mini])放在最右边和最左边,这样排序效率是原来的2倍
- ①单趟排序
找到最小的数字(a[mini])和最大的数字(a[maxi]),将它们放在最左边和最右边
ps:其中的begin,end保存记录左右的下标,mini,maxi记录保存最小值和最大值的下标
- ②整个数组排序
begin++和end--这样下次就可以排剩下的n-2个数字,再次进行单趟,如此可构成循环,直到begin小于end
整体代码:
void SelectSort(int* a, int n)
{
int begin = 0,end = n - 1;
while (begin<end)
{
int mini = begin, maxi = begin;
for (int i = begin; i <= end; i++)
{
if (a[i] < a[mini])
{
mini = i;
}
if (a[i] > a[maxi])
{
maxi = i;
}
}
Swap(&a[mini], &a[begin]);
//当begin==maxi时,最大值会被换走,修正一下
if (begin==maxi)
{
maxi=mini;
}
Swap(&a[maxi], &a[end]);
begin++;
end--;
}
}
直接选择排序总结:
- ①直接选择排序很好理解,但实际效率不高,很少使用
- ②时间复杂度:O(N^2)
- ③空间复杂度:O(1)
四、堆排序
基本思想:
- 1、将待排序的序列构造成一个大堆,根据大堆的性质,当前堆的根节点(堆顶)就是序列中最大的元素;
- 2、将堆顶元素和最后一个元素交换,然后将剩下的节点重新构造成一个大堆;
- 3、重复步骤2,如此反复,从第一次构建大堆开始,每一次构建,我们都能获得一个序列的最大值,然后把它放到大堆的尾部。最后,就得到一个有序的序列了。
- 小结论: 排升序,建大堆 排降序,建小堆
具体实现:、
- ①向下调整算法
我们将给定的数组序列,建成一个大堆,建堆从根节点开始就需要多次的向下调整算法
堆的向下调整算法(使用前提): (1)若想将其调整为小堆,那么根结点的左右子树必须都为小堆。 (2)若想将其调整为大堆,那么根结点的左右子树必须都为大堆。
向下调整算法的基本思想:
- 1、从根节点开始,选出左右孩子值较大的一个
- 2、如果选出的孩子的值大于父亲的值,那么就交换两者的值
- 3、将大的孩子看做新的父亲,继续向下调整,直到调整到叶子节点为止
//向下调整算法
//以建大堆为例
void AdJustDown(int* a, int n, int parent)
{
int child = parent * 2 + 1;
//默认左孩子较大
while (child < n)
{
if (child + 1 < n && a[child+1] > a[child ])//如果这里右孩子存在,
//且更大,那么默认较大的孩子就改为右孩子
{
child++;
}
if(a[child]>a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
- ②建堆(将给定的任意数组建成大堆)
建堆思想: 从倒数第一个非叶子节点开始,从后往前,依次将其作为父亲,依次向下调整,一直调整到根的位置
建堆图示:
//最后一个叶子结点的父亲为i,从后往前,依次向下调整,直到调到根的位置
for (int i = (n - 1 - 1) / 2;i>=0;--i)
{
AdJustDown(a,n,i);
}
- ③堆排序(利用堆删的思想进行)
堆排序的思想: 1、建好堆之后,将堆顶的数字与最后一个数字交换 2、将最后一个数字不看,剩下的n-1个数字再向下调整成堆再进行第1步 3、直到最后只剩一个数停止,这样就排成有序的了
for (int end = n - 1; end > 0; --end)
{
Swap(&a[end],&a[0]);
AdJustDown(a,end,0);
}
整体代码如下:
void AdJustDown(int* a, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
if (child + 1 < n && 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 HeapSort(int*a,int n)
{
for (int i = (n - 1 - 1) / 2;i>=0;--i)
{
AdJustDown(a,n,i);
}
for (int end = n - 1; end > 0; --end)
{
Swap(&a[end],&a[0]);
AdJustDown(a,end,0);
}
}
五、冒泡排序
冒泡排序的基本思想:
一趟过程中,前后两个数依次比较,将较大的数字往后推,下一次只需要比较剩下的n-1个数,如此往复
//优化版本的冒泡排序
void BubbleSort(int* a, int n)
{
int end = n-1;
while (end>0)
{
int exchange = 0;
for (int i = 0; i < end; i++)
{
if (a[i] > a[i + 1])
{
Swap(&a[i], &a[i + 1]);
exchange = 1;
}
}
if (exchange == 0)//单趟过程中,若没有交换过,证明已经有序,没有必要再排序
{
break;
}
end--;
}
}
冒泡排序总结:
- ①非常容易理解的排序
- ②时间复杂度:O(N^2)
- ③空间复杂度:O(1)
六、快速排序
递归版本
1、hoare版本
hoare的单趟思想: 1、左边作key,右边先走找到比key小的值 2、左边后走找到大于key的值 3、然后交换left和right的值 4、一直循环重复上述1 2 3步 5、两者相遇时的位置,与最左边选定的key值交换 这样就让key到达了正确的位置上
动图演示:
//hoare版本
//单趟排序 让key到正确的位置上 keyi表示key的下标,并不是该位置的值
int partion1(int* a, int left, int right)
{
int keyi = left;//左边作keyi
while (left < right)
{ //右边先走,找小于keyi的值
while (left < right && a[right] >= a[keyi])
{
right--;
}
//左边后走,找大于keyi的值
while (left < right && a[left] <= a[keyi])
{
left++;
}
Swap(&a[left], &a[right]);
}
Swap(&a[left], &a[keyi]);
return left;
}
void QuickSort(int* a, int left, int right)
{
if (left >= right)
return;
int keyi = partion1(a, left, right);
//[left,keyi-1] keyi [keyi+1,right]
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
2、挖坑法
其实本质上是hoare的变形
挖坑法单趟思想: 1、先将最左边第一个数据存放在临时变量key中,形成一个坑位 2、右边先出发找到小于key的值,然后将该值丢到坑中去,此时形成一个新坑位 3、左边后出发找到大于key的值,将该值丢入坑中去,此时又形成一个新的坑位 4、一直循环重复1 2 3步 5、直到两边相遇时,形成一个新的坑,最后将key值丢进去 这样key就到达了正确的位置上了
动图演示:
//挖坑法
int partion2(int* a, int left, int right)
{
int key = a[left];
int pit = left;
while (left < right)
{
while (left < right && a[right] >= key)
{
right--;
}
a[pit] = a[right];//填坑
pit=right;
while (left < right && a[left] <= key)
{
left++;
}
a[pit] = a[left];//填坑
pit=left;
}
a[pit] = key;
return pit;
}
void QuickSort(int* a, int left, int right)
{
if (left >= right)
return;
int keyi = partion2(a, left, right);
//[left,keyi-1] keyi [keyi+1,right]
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
3、前后指针法(推荐这种写法)
前后指针的思想:
1、初始时选定prev为序列的开始,cur指针指向prev的后一个位置,同样选择最左边的第一个数字作为key 2、cur先走,找到小于key的值,找到就停下来 3、++prev 4、交换prev和cur为下标的值 5、一直循环重复2 3 4步,停下来后,最后交换key和prev为下标的值
这样key同样到达了正确的位置
动图演示:
int partion3(int* a, int left, int right)
{
int prev = left;
int cur = left + 1;
int keyi = left;
while (cur <= right)
{
if (a[cur] < a[keyi] && ++prev != cur)//prev != cur 防止cur和prev相等时,相当于自己和自己交换,可以省略
{ //前置 ++ 的优先级大于 != 不等于的优先级
Swap(&a[prev], &a[cur]);
}
++cur;
}
Swap(&a[keyi], &a[prev]);
return prev;
}
void QuickSort(int* a, int left, int right)
{
if (left >= right)
return;
int keyi = partion3(a, left, right);
//[left,keyi-1] keyi [keyi+1,right]
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
递归展开图
快速排序的优化
1、三数取中法
快速排序对于数据是敏感的,如果这个序列是非常无序,杂乱无章的,那么快速排序的效率是非常高的,可是如果数列有序,时间复杂度就会从O(N*logN)变为O(N^2),相当于冒泡排序了
若每趟排序所选的key都正好是该序列的中间值,即单趟排序结束后key位于序列正中间,那么快速排序的时间复杂度就是O(NlogN)
但是这是理想情况,当我们面对一组极端情况下的序列,就是有序的数组,选择左边作为key值的话,那么就会退化为O(N^2)的复杂度,所以此时我们选择首位置,尾位置,中间位置的数分别作为三数,选出中间位置的数,放到最左边,这样选key还是从左边开始,这样优化后,全部都变成了理想情况
//快排的优化
//三数取中法
int GetMidIndex(int* a, int left, int right)
{
int mid = (left + right) / 2;
if (a[left] < a[right])
{
if (a[mid] < a[right])
{
return mid;
}
else if (a[mid] > a[right])
{
return right;
}
else
{
return left;
}
}
else
{
if (a[mid] > a[left])
{
return left;
}
else if (a[mid] < a[right])
{
return right;
}
else
{
return mid;
}
}
}
int partion5(int* a, int left, int right)
{
//三数取中,面对有序时是最坏的情况O(N^2),现在每次选的key都是中间值,变成最好的情况了
int midi = GetMidIndex(a, left, right);
Swap(&a[midi], &a[left]);//这样还是最左边作为key
int prev = left;
int cur = left + 1;
int keyi = left;
while (cur <= right)
{
if (a[cur] < a[keyi] && ++prev != cur)//prev != cur 防止cur和prev相等时,相当于自己和自己交换,可以省略
{ //前置 ++ 的优先级大于 != 不等于的优先级
//++prev;
Swap(&a[prev], &a[cur]);
}
++cur;
}
Swap(&a[keyi], &a[prev]);
return prev;
}
2、递归到小子区间
随着递归深度的增加,递归次数以每层2倍的速度增加,这对效率有着很大的影响,当待排序序列的长度分割到一定大小后,继续分割的效率比插入排序要差,此时可以使用插排而不是快排
我们可以当划分区间长度小于10的时候,用插入排序对剩下的数进行排序
//小区间优化法,可以采用直接插入排序
void QuickSort(int* a, int left, int right)
{
if (left >= right)
return;
if (right - left + 1 < 10)
{
InsertSort(a + left, right - left + 1);
}
else
{
int keyi = partion5(a, left, right);
//[left,keyi-1] keyi [keyi+1,right]
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
}
非递归版本
递归的算法主要是在划分子区间,如果要非递归实现快排,只要使用一个栈来保存区间就可以了。一般将递归程序改成非递归首先想到的就是使用栈,因为递归本身就是一个压栈的过程。
非递归的基本思想: 1. 申请一个栈,存放排序数组的起始位置和终点位置。 2. 将整个数组的起始位置和终点位置入栈。 3. 由于栈的特性是:后进先出,right后进栈,所以right先出栈。 定义一个end接收栈顶元素,出栈操作、定义一个begin接收栈顶元素,出栈操作。 4. 对数组进行一次单趟排序,返回key关键值的下标。 5. 这时候需要排基准值key左边的序列。 如果只将基准值key左边序列的起始位置和终点位置存入栈中,等左边排序完将找不到后边的区间。所以先将右边序列的起始位置和终点位置存入栈中,再将左边的起始位置和终点位置后存入栈中。 6.判断栈是否为空,若不为空 重复4、5步、若为空则排序完成。
void QuickSortNonR(int* a, int left, int right)
{
Stack st;
StackInit(&st);
StackPush(&st,left);
StackPush(&st, right);
while (!StackEmpty(&st))
{
int end = StackTop(&st);
StackPop(&st);
int begin = StackTop(&st);
StackPop(&st);
int keyi = partion5(a,begin,end);
//区间被成两部分了 [begin,keyi-1] keyi [keyi+1,end]
if (keyi + 1 < end)
{
StackPush(&st,keyi+1);
StackPush(&st,end);
}
if (keyi-1>begin)
{
StackPush(&st, begin);
StackPush(&st, keyi -1);
}
}
StackDestroy(&st);
}
快速排序的总结:
- ①快排的整体综合性能和使用场景都是比较好的,所以才敢叫快速排序
- ②快排唯一死穴,就是排一些有序或者接近有序的序列,例如 2,3,2,3,2,3,2,3这样的序列时,会变成O(N^2)的时间复杂度
- ③时间复杂度O(N*logN)
- ④空间复杂度O(logN)
七、归并排序
归并排序的基本思想(分治思想):
- 1、(拆分)将一段数组分为左序列和右序列,让他们两个分别有序,再将左序列细分为左序列和右序列,如此重复该步骤,直到细分到区间不存在或者只有一个数字为止
- 2、(合并)将第一步得到的数字合并成有序区间
具体实现:
- ①拆分
- ②合并
递归实现:
从思想上来说和二叉树很相似,所以我们可以用递归的方法来实现归并排序
代码如下:
void _MergeSort(int* a, int left, int right, int* tmp)
{
if (left >= right)
{
return;
}
int mid = (left + right) / 2;
_MergeSort(a, left, mid, tmp);
_MergeSort(a, mid+1, right, tmp);
int begin1 = left, end1 = mid;
int begin2 = mid + 1, end2 = right;
int i = left;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
{
tmp[i++] = a[begin1++];
}
else
{
tmp[i++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[i++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[i++] = a[begin2++];
}
for (int j = left; j <= right; j++)
{
a[j] = tmp[j];
}
}
//归并排序
void MergeSort(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int)*n);
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
_MergeSort(a,0,n-1,tmp);
free(tmp);
tmp = NULL;
}
非递归实现:
我们知道,递归实现的缺点就是会一直调用栈,而栈内存往往是很小的。所以,我们尝试着用循环的办法去实现
由于我们操纵的是数组的下标,所以我们需要借助数组,来帮我们存储上面递归得到的数组下标,和递归的区别就是,递归要将区间一直细分,要将左区间一直递归划分完了,再递归划分右区间,而借助数组的非递归是一次性就将数据处理完毕,并且每次都将下标拷贝回原数组
归并排序的基本思路是将待排序序列a[0…n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。
但是我们这是理想情况下(偶数个),还有特殊的边界控制,当数据个数不是偶数个时,我们所分的gap组,势必会有越界的地方
第一种情况:
第二种情况:
代码如下:
void MergeSortNonR(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int)*n);
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
int gap = 1;
while (gap < n)
{
for (int i = 0; i < n; i += 2 * gap)
{
// [i,i+gap-1] [i+gap,i+2*gap-1]
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
// 核心思想:end1、begin2、end2都有可能越界
// end1越界 或者 begin2 越界都不需要归并
if (end1 >= n || begin2 >= n)
{
break;
}
// end2 越界,需要归并,修正end2
if (end2 >= n)
{
end2 = n- 1;
}
int index = i;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
{
tmp[index++] = a[begin1++];
}
else
{
tmp[index++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[index++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[index++] = a[begin2++];
}
// 把归并小区间拷贝回原数组
for (int j = i; j <= end2; ++j)
{
a[j] = tmp[j];
}
}
gap *= 2;
}
free(tmp);
tmp = NULL;
}
归并排序的总结:
- ①缺点是需要O(N)的空间复杂度,归并排序更多的是解决磁盘外排序的问题
- ②时间复杂度:O(N*logN)
- ③空间复杂度:O(N)
八、计数排序
又叫非比较排序,又称为鸽巢原理,是对哈希直接定址法的变形应用
基本思想:
- 1、统计相同元素出现的个数
- 2、根据统计的结果,将数据拷贝回原数组
具体实现:
- ①统计相同元素出现的个数
对于给定的任意数组a,我们需要开辟一个计数数组count,a[i]是几,就对count数组下标是几++
这里我们用到了绝对映射,即a[i]中的数组元素是几,我们就在count数组下标是几的位置++,但是对于数据比较聚集,不是从较小的数字开始,例如1001,1002,1003,1004这样的数据,我们就可以用到相对映射的方法,以免开辟数组空间的浪费,count数组的空间大小我们可以用a数组中最大值减去最小值+1来确定(即:range=max-min+1),我们可以得到count数组下标 j =a[i]-min
- ②根据count数组的结果,将数据拷贝回a数组
count[j]中数据是几,说明该数出现了几次,是0就不用拷贝
代码如下:
void CountSort(int* a, int n)
{
int min = a[0], max = a[0];//如果不赋值,min和max就是默认随机值,最好给赋值一个a[0]
for (int i=1;i<n;i++)//修正 找出A数组中的最大值和最小值
{
if (a[i] < min)
{
min=a[i];
}
if (a[i]>max)
{
max=a[i];
}
}
int range = max - min + 1;//控制新开数组的大小,以免空间浪费
int* count = (int*)malloc(sizeof(int) * range);
memset(count,0, sizeof(int) * range);//初始化为全0
if (count==NULL)
{
printf("malloc fail\n");
exit(-1);
}
//1、统计数据个数
for (int i=0;i<n;i++)
{
count[a[i]-min]++;
}
//2、拷贝回A数组
int j = 0;
for (int i=0;i<range;i++)
{
while (count[i]--)
{
a[j++] = i + min;
}
}
free(count);
count = NULL;
}
计数排序总结:
- ①在数据范围比较集中时,效率很高,但是使用场景很有限,可以排负数,但对于浮点数无能为力
- ②时间复杂度:O(MAX(N,range))
- ③空间复杂度:O(range)
八大排序的稳定性总结:
稳定的排序有:直接插入排序、冒泡排序、归并排序
不稳定的排序有:希尔排序、选择排序、堆排序、快速排序、计数排序
相关推荐
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
-
Mysql和Oracle实现序列自增/*ORACLE设置自增序列oracle本身不支持如mysql的AUTO_INCREMENT自增方式,我们可以用序列加触发器的形式实现,假如有一个表T_WORKM...
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
-
概述今天主要简单介绍一下Oracle12c的一些新特性,仅供参考。参考:http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT...
- MySQL CREATE TABLE 简单设计模板交流
-
推荐用MySQL8.0(2018/4/19发布,开发者说同比5.7快2倍)或同类型以上版本....
- mysql学习9:创建数据库(mysql5.5创建数据库)
-
前言:我也是在学习过程中,不对的地方请谅解showdatabases;#查看数据库表createdatabasename...
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
-
执行"CREATETABLE新表ASSELECT*FROM原表;"后,新表与原表的字段一致,但主键、索引不会复制到新表,会把原表的表记录复制到新表。...
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
-
在街上看到的PandaDunk的超载可能让一些球鞋迷们望而却步,但Dunk的浪潮仍然强劲,看不到尽头。我们看到的很多版本都是为女性和儿童制作的,这种新配色为后者引入了一种令人耳目一新的新选择,而...
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
-
多功能雷达AN/SPY-1的特性和技术能力,该雷达已经在美国海军服役了30多年,其修改-AN/SPY-1A、AN/SPY-1B(V)、AN/SPY-1D、AN/SPY-1D(V),以及雷神...
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
-
全面分析汽车音响使用或安装技术常识一:主机是大多数人最熟习的音响器材,有关主机的各种性能及规格,也是耳熟能详的事,以下是一些在使用或安装时,比较需要注意的事项:LOUDNESS:几年前的主机,此按...
- 【推荐】ProAc Response系列扬声器逐个看
-
有考牌(公认好声音)扬声器之称ProAcTablette小音箱,相信不少音响发烧友都曾经,或者现在依然持有,正当大家逐渐掌握Tablette的摆位设定与器材配搭之后,下一步就会考虑升级至表现更全...
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
-
作者:初吻给了烟sco混迹张大妈时日不短了,手没少剁。家里有了汪星人,吸尘器使用频率相当高,偶尔零星打扫用卧式的实在麻烦(汪星人:你这分明是找借口,我掉毛是满屋子都有,铲屎君都是用卧式满屋子吸的,你...
- 专题|一个品牌一件产品(英国篇)之Quested(罗杰之声)
-
Quested(罗杰之声)代表产品:Q212FS品牌介绍Quested(罗杰之声)是录音监听领域的传奇品牌,由英国录音师RogerQuested于1985年创立。在成立Quested之前,Roger...
- 常用半导体中英对照表(建议收藏)(半导体英文术语)
-
作为一个源自国外的技术,半导体产业涉及许多英文术语。加之从业者很多都有海外经历或习惯于用英文表达相关技术和工艺节点,这就导致许多英文术语翻译成中文后,仍有不少人照应不上或不知如何翻译。为此,我们整理了...
- Fyne Audio F502SP 2.5音路低音反射式落地音箱评测
-
FyneAudio的F500系列,有新成员了!不过,新成员不是新的款式,却是根据原有款式提出特别版。特别版产品在原有型号后标注了SP字样,意思是SpecialProduction。Fyne一共推出...
- 有哪些免费的内存数据库(In-Memory Database)
-
以下是一些常见的免费的内存数据库:1.Redis:Redis是一个开源的内存数据库,它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合。Redis提供了快速的读写操作,并且支持持久化数据到磁...
- RazorSQL Mac版(SQL数据库查询工具)
-
RazorSQLMac特别版是一款看似简单实则功能非常出色的SQL数据库查询、编辑、浏览和管理工具。RazorSQLformac特别版可以帮你管理多个数据库,支持主流的30多种数据库,包括Ca...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
推荐7个模板代码和其他游戏源码下载的网址
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
- MySQL CREATE TABLE 简单设计模板交流
- mysql学习9:创建数据库(mysql5.5创建数据库)
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
- 【推荐】ProAc Response系列扬声器逐个看
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)