论文网站建设的参考文献公司网站优化去哪里学
news/
2025/9/30 2:15:56/
文章来源:
论文网站建设的参考文献,公司网站优化去哪里学,河南微网站开发,看课学校网站建设文章目录 1、冒泡排序/选择排序/插入排序冒泡排序(Bubble Sort)选择排序(Selection Sort)插入排序(Insertion Sort) 2、希尔排序(Shells Sort)3、快速排序(Quick Sort)4、堆排序(Heap Sort)5、归并排序(Merge Sort)6、桶排序/计数排序/基数排序桶排序(Bucket sort)计数排序(Cou… 文章目录 1、冒泡排序/选择排序/插入排序冒泡排序(Bubble Sort)选择排序(Selection Sort)插入排序(Insertion Sort) 2、希尔排序(Shells Sort)3、快速排序(Quick Sort)4、堆排序(Heap Sort)5、归并排序(Merge Sort)6、桶排序/计数排序/基数排序桶排序(Bucket sort)计数排序(Counting Sort)基数排序(Radix Sort) 注以下排序默认为升序排序。 稳定性指的是排序的过程中是否会改变多个相同的值的相对次序如果会改变则是不稳定的。
1、冒泡排序/选择排序/插入排序
冒泡排序选择排序插入排序是最简单的排序方法。
冒泡排序(Bubble Sort)
排序方法扫描的过程中比较相邻两个数的大小关系如果存在逆序就交换这两个数这样每趟可以保证最后一个数也就是最大的数一步步交换上去如气泡上浮一样回归到正确的位置。
时间复杂度 O ( n 2 ) O(n^2) O(n2)
稳定性稳定。对于两个相同的值不会发生交换。
代码实现
int arr[] {0, 2, 9, 3, 5, 7, 8, 1, 4, 6};//arr是被排序数组start是起点坐标end是终点坐标闭区间void sort(int* arr, int start, int end) {int n end - start 1;//只需要排序n - 1次for (int i 1; i n; i) {//倒数i - 1个数已经归位不必交换for (int j start; j end - i; j) {//出现逆序if (arr[j 1] arr[j]) {int tmp arr[j];arr[j] arr[j 1];arr[j 1] tmp;}}}
}选择排序(Selection Sort)
排序方法扫描的过程中每次选择剩余未排序的数组中选择最小值与未排序部分第一个值进行交换从而使得未排序部分的第一个位置得到正确的值。
时间复杂度 O ( n 2 ) O(n^2) O(n2)
稳定性不稳定。例如3 3 2 → 一次交换 \stackrel{一次交换}{\rightarrow} →一次交换 2 3 3 可以发现两个3的位置改变了。
代码实现
int arr[] {0, 2, 9, 3, 5, 7, 8, 1, 4, 6};//arr是被排序数组start是起点坐标end是终点坐标闭区间void sort(int* arr, int start, int end) {int n end - start 1;//只需要排序n - 1次for (int i 1; i n; i) {int min_element_positon start i - 1;for (int j start i - 1; j end; j) {if (arr[j] arr[min_element_positon]) {min_element_positon j;}}int tmp arr[min_element_positon];arr[min_element_positon] arr[start i - 1];arr[start i - 1] tmp;}
}插入排序(Insertion Sort)
排序方法每次取未排序部分的数组将其插入到前半已经排序后的数组内类似打牌时整理牌序的方法插入到前面整理好的数组内的合适的位置。
时间复杂度 O ( n 2 ) O(n^2) O(n2)
稳定性稳定。相同的值符合大于等于关系并不会插入到相同值的前面。
代码实现
int arr[] {0, 2, 9, 3, 5, 7, 8, 1, 4, 6};//arr是被排序数组start是起点坐标end是终点坐标闭区间void sort(int* arr, int start, int end) {int n end - start 1;//只需要排序n - 1次for (int i 1; i n; i) {int key arr[start i];int j start i;while (j start) {if (j start) break; // 如果是最小值会一直到开头if (j start i key arr[j - 1]) break; //如果是最大值if (key arr[j - 1] key arr[j 1]) break;//在中间合适的值arr[j] arr[j - 1];j--;}arr[j] key;}
}2、希尔排序(Shell’s Sort)
排序方法每次选择特定的增量对这个增量下的子序列进行直接插入排序。
最好时间复杂度 O ( n log n ) O(n\log{n}) O(nlogn)
最坏时间复杂度 O ( n n ) O(n\sqrt{n}) O(nn )【选取d{1, 2, 4, 8, …2k}大到小】$O(n\log{n}\log{n})$【选取2m*2^n次大到小的集合】
关于时间复杂度的证明主要考虑对于两个不同增量的序列的插入排序两者的结果都是可以互相继承的以及相关其他复杂度的 分析
稳定性不稳定因为不同序列相同的值的位置可能改变。
代码实现
int arr[] {0, 2, 9, 55, 54, 7, 8, 1, 40, 600};void sort(int* arr, int start, int end) {int n end - start 1;for (int d n / 2; d 1; d / 2) {//倍减for (int i d; i n; i) {//一共进行n - d次插入int tmp arr[start i];//取无序部分第一个数进行插排int j i - d;for (; j 0 tmp arr[j start]; j - d) {arr[j d start] arr[j start];}//如果前面有比最后一个数小的就腾出一位//实际上会多减一次要补回darr[j d start] tmp;}}
}3、快速排序(Quick Sort)
排序方法“挖坑填数”取出需要排序区间的第一个数作为基数利用双指针方法整理当前数组使得这个数组成为坑左边均为小于等于基数的数坑右边都是大于等于基数的数最后把基数填入这个位置此处基数回到正确的位置。然后分成两个区间递归分治重复上述操作。
一般时间复杂度 O ( n log ( n ) ) O(n\log(n)) O(nlog(n))
最坏时间复杂度例如数组已经有序的时候 O ( n 2 ) O(n^2) O(n2)
稳定性不稳定。例如 6 3 3 经过一次的填坑得到 3 3 _ 3的次序发生了改变。
代码实现
int arr[] {0, 2, 9, 3, 5, 7, 8, 1, 4, 6};//arr是被排序数组start是起点坐标end是终点坐标闭区间void sort(int* arr, int start, int end) {if (start end) { //如果只有1个元素或者没有元素就不需要排序return;}//目的是把数组整理成一半小于等于基数一半大于等于基数中间是坑位的样子int l start, r end, key arr[l];//取第一个元素作为基数while (l r) {while (l r arr[r] key) {r--;//从后往前找到第一个小于key的值}if (l r) {//如果相遇则说坑位左右两侧都已经整理完毕arr[l] arr[r];}while (l r arr[l] key) {l;//从前往后找到第一个大于key的值}if (l r) {arr[r--] arr[l];}}arr[l] key;sort(arr, start, l - 1);sort(arr, l 1, end);
}4、堆排序(Heap Sort)
排序方法利用标号关系构造一个无序堆通过堆调整形成一个有序的大顶堆。每次取堆顶的数和未排序数的最大标号即堆底最后一个叶子交换位置此时最后一个叶子是当前未排序的数中最大的数已经回到正确的位置离开堆。之后调整堆维护大顶堆的性质等待下一次交换。
关于堆调整如果父节点最大不交换如果父节点不是最大则要交换左右儿子中较大的一个交换后可以使得原来那个较小儿子所在的子树的父节点变成较大儿子这样保证较小儿子的子树符合二叉堆的性质并且根节点也符合条件但是可能会影响较另外子数成堆所以为了维护堆的性质要一直交换下去直到符合性质最坏可能要交换到叶子但是这样的交换不超过 log n \log{n} logn次因为每次交换都可以使得近似大小的另一子树符合堆的性质需要维护的堆的性质的节点数倍减直至单个节点单个节点符合堆的性质。
时间复杂度 O ( n log n ) O(n\log{n}) O(nlogn)
时间复杂度分析开始的堆调整 n n n次之后每个数取出后的堆调整的交换次数取决于二叉堆的深度由于二叉堆是一个完全二叉树所以深度不超过 log n \log{n} logn所以一趟的交换次数不超过 log n \log{n} logn次。
稳定性不稳定。如果是全相等的堆仍然会进行交换。
代码实现
int arr[] {0, 2, 9, 3, 5, 7, 8, 1, 4, 6};//arr是被排序数组start是起点坐标end是终点坐标闭区间
//堆调整函数维护当前子树堆的性质
void heap_modify(int* arr, int root_id, int last_id, int start) {int tmp arr[root_id start];for (int i 2 * root_id 1; i last_id; i i * 2 1) {//枚举左儿子if (i last_id arr[i start] arr[i 1 start]) {//如果有右儿子并且右儿子更大取右儿子进行比较//否则取左儿子i;}//较大的儿子和根节点进行比较都是和原来根节点交换的数进行比较if (arr[i start] tmp) {arr[root_id start] arr[i start];root_id i;//较大的儿子的id是根节点的下一个id}else {//如果较大的儿子不大于根节点不必调整下去break;}}arr[root_id start] tmp;//填坑
}
void sort(int* arr, int start, int end) {//构造有序堆for (int i end; i start; i--) {//映射成0~n的标号,倒着整理heap_modify(arr, i - start, end - start, start);}int n end - start 1;for (int i 1; i n; i) {//n - 1趟int tmp arr[start];arr[start] arr[end - i 1];//与当前无序数组最大下标交换arr[end - i 1] tmp;heap_modify(arr, 0, end - i - start, start);//维护堆的性质}
}5、归并排序(Merge Sort)
排序方法利用分治的思想将数组不断划分到单个数然后递归合并起来利用双指针的手法将两个有序数组合并成一个有序的数组。
时间复杂度 O ( n log n ) O(n\log{n}) O(nlogn)
稳定性稳定合并的数组的时候如果两个值相同的话会按照原先的顺序依次放入到临时数组当中。
代码实现
int arr[] {0, 2, 9, 55, 54, 7, 8, 1, 40, 600};
int tmp[1000];
void merge_arr(int* arr, int* tmp, int start, int end, int mid) {int i start, j mid 1, p 0;//要保证归并排序的稳定性的时候优先取左侧while (i mid j end) {if (arr[i] arr[j]) {tmp[p] arr[i];} else {tmp[p] arr[j];}}//当一个数组填完了剩余的部分要填完也就是另一个数组内不存在小于等于这个数的数据了while (i mid) {tmp[p] arr[i];}while (j end) {tmp[p] arr[j];}//回填入数组for (int k start; k end; k) {arr[k] tmp[k - start];}
}
void sort(int* arr, int start, int end) {//二分区间if (start end) {//这个条件需要否则会无限递归int mid (start end) 1;sort(arr, start, mid);//分成start~mid mid1~end两个区间sort(arr, mid 1, end);merge_arr(arr, tmp, start, end, mid);}
}6、桶排序/计数排序/基数排序
桶排序(Bucket sort)
排序方法将输入值的值域划分成若干个区间分别放入到桶中再用其他排序方法对桶内的元素进行排序类似分块分治。
时间复杂度取决于桶内排序算法的时间复杂度以及分类后所在的桶的数目如果使用堆排序来进行桶内排序的话并且最后均匀地分入到k个桶内那么时间复杂度是 O ( n n log n k ) O(nn\log{\frac{n}{k}}) O(nnlogkn)当桶足够多时覆盖了值域的时候便是 O ( n ) O(n) O(n)的计数排序。
稳定性取决于给桶内排序的算法的稳定性如果是插入排序就是稳定的如果是堆排序或者快速排序就是不稳定的。
代码实现
int arr[] {0, 2, 9, 3, 5, 7, 8, 1, 4, 6};//arr是被排序数组start是起点坐标end是终点坐标闭区间void sort(int* arr, int start, int end, int bucket_size) {int min_value arr[start];int max_value arr[start];//获得值域for (int i start; i end; i) {if (arr[i] min_value) {min_value arr[i];}if (arr[i] max_value) {max_value arr[i];}}int val_area max_value - min_value 1;int bucket_nums (val_area bucket_size - 1) / bucket_size;//获得向上取整的桶的数目//如果此处size为4分成 0~3, 4~7, 8~9三个桶标号分别是0 1 2for (int i start; i end; i) {int x arr[i];int id (x - min_value) / bucket_size;buckets[id][elements_in_bukect[id]] x;//填入一个数字}for (int i 0; i bucket_nums; i) {if (elements_in_bukect[i] 0) continue;int len elements_in_bukect[i];heap_sort(buckets[i], 0, len - 1);}//回收排序好的数字int p 0;for (int i 0; i bucket_nums; i) {if (elements_in_bukect[i] 0) continue;int len elements_in_bukect[i];for (int j 0; j len; j) {arr[p start] buckets[i][j];p;}}
}计数排序(Counting Sort)
排序方法计数排序是桶排序中桶的数量和值域长度相同的时候就是一次读入数据放入到对应值的桶内最后遍历值域输出排序好的数组。
时间复杂度 O ( n k ) O(nk) O(nk)其中k是值域长度n是元素数目。
稳定性稳定。按序读入相同值按序拷贝出来。笔者想了想直接用一维数组有点难以体现稳定性如果用可变长数组或者链表来实现的话就能维护相同值的相对次序每个链表存入该值的id。或者用二维数组。
代码实现
int arr[] {0, 2, 9, 3, 5, 7, 8, 1, 4, 6};//这里没有用链表
int cnt[100];
void sort(int* arr, int start, int end) {int min_value arr[start];int max_value arr[start];for (int i start; i end; i) {if (arr[i] min_value) {min_value arr[i];}if (arr[i] max_value) {max_value arr[i];}}for (int i start; i end; i) {cnt[arr[i] - min_value];}int p start;for (int i 0; i max_value - min_value; i) {for (int j 0; j cnt[i]; j) {arr[p] i min_value;}}
}基数排序(Radix Sort)
排序方法基数排序相当于对每一位作计数排序。
时间复杂度 O ( k ⋅ n ) O(k·n) O(k⋅n)其中k是最大数的某进制形式下的数码长度通常是十进制
原理说明手写高位到低位分别是主要关键字次要关键字次次关键字最次关键字。首先我们根据最低位排序如果后面高位不相同会按照高位排序如果高位相同的话但是低位不相同计数排序具有稳定性不会改变低位已经排好的顺序。
稳定性稳定。同上。
注意基数排序的需要非负整数如果有负数的话需要调整为非负整数。
代码实现
int arr[] {0, 2, 9, 3, 5, 7, 8, 1, 40, 600};//这里没有用链表
int buckets[10][10000];//数码桶一个桶里可以装10000个数
int elements_in_bucket[10];//数码桶内数有多少
void sort(int* arr, int start, int end) {int max_value arr[start];for (int i start; i end; i) {if (arr[i] max_value) {max_value arr[i];}}int max_length 0;while (max_value 0) {max_length;max_value / 10;}if (max_length 0) return;//如果都是0for (int i 0, base 1; i max_length; i, base * 10) {//对每一位进行排序for (int j start; j end; j) {int digit arr[j] / base % 10;//存入某位数码为digit的桶buckets[digit][elements_in_bucket[digit]] arr[j];//桶内数目elements_in_bucket[digit];}int index start;for (int j 0; j 10; j) {//遍历数码桶if (elements_in_bucket[j] ! 0) {for (int k 0; k elements_in_bucket[j]; k) {arr[index] buckets[j][k];}}elements_in_bucket[j] 0;//}}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/922409.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!