排序的关键字
-
时间复杂度:整个排序算法运行所需要的时间。
-
空间复杂度:排序算法运行过程汇总所需要额外空间
-
稳定性:若待排的序列中有大小相同的两个数,若整个排序过程中不存在两数次序交换的可能新内阁,则该排序算法是稳定的。
-
in-place:算法使用的额外存储空间是常数级的
一,最基本的冒泡排序——Bubble Sort。
public void swap(int[] data, int i, int j) { if (i != j) {
data[i] = data[i] + data[j];
data[j] = data[i] - data[j];
data[i] = data[i] - data[j];
}
}
二,冒泡排序(递增)
冒泡排序,是所有排序中最简单的一种,也是效率最低的一种,时间复杂度O(n2),空间复杂度O(n)。冒泡排序没有改变原始元素的相对位置,因此是稳定的排序。
public void bubble_sort(int[] data) {
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data.length; j++) {
if (data[j] > data[j + 1]) {
swap(data, j, j + 1);
}
}
}
}
三,插入排序(递增)
插入排序也是一种比较简单的排序方法,它的基本原理就好似我们打牌过程中摸牌理牌那一环,当你摸到一张牌后将其插入到合适的位置。
插入排序首先定位一个数(一般从第二个开始),将这个数依次与位于它之前的数进行比较,经过一轮比较,找到它在这些数中适当的位置。然后定位下一个数,再找到合适的为止,依次进行直到最后一个数。
例如(5 2 1 4 3),黑体为进行交换的两数。
-
第一轮:
(2 5 1 4 3)
-
第二轮:
(2 1 5 4 3)
(1 2 5 4 3)
-
第三轮:
(1 2 4 5 3)
(1 2 4 5 3)
(1 2 4 5 3)
-
第四轮:
(1 2 4 3 5)
(1 2 3 4 5)
(1 2 3 4 5)
(1 2 3 4 5)排序完成
public void insertion_sort(int[] data) {
int key = 0;
int j = 0;
for (int i = 1; i < data.length; i++) {
key = data[i];
j = i - 1;
while (j >= 0 && data[j] > key) {
swap(data, j, j + 1);
j = j - 1;
}
}
}
排序插入在数据集较大的时候效率会变得恨低,但是它易于实现,处理小型数据集时效率较高,同时也是稳定的,in-place的,它的时间复杂度是O(n2),空间复杂度是O(n)。
四,选择排序
选择排序的工作原理
-
找到数据集中的最小元素
-
将最小元素与未排序声誉元素的第一个元素交换
-
对剩余元素进行以上步骤
它的时间复杂度是O(n2),空间复杂度是O(n),同插入排序类似,它也不适用于大数据集。但是它易于实现,也是一种in-place的排序算法。对于稳定性:简易实现是不稳定的,例如(3 5 5 2),在第二轮中第二个五会被认为是最小的,然后同第一个五进行交换。
public void selection_sort(int[] data) {
int minimum = 0;
for (int i = 0; i < data.length - 1; i++) {
minimum = i;
for (int j = i + 1; j < data.length; j++) {
if (data[j] < data[minimum]) {
minimum = j;
}
}
swap(data, i, minimum);
}
}
五,ELFHash
public int ELFHash(String str, int number) {
int hash = 0;
long x = 0L;
char[] array = str.toCharArray();
for (int i = 0; i < array.length; i++) {
hash = (hash << 4) + array[i];
if ((x = (hash & 0xF0000000L)) != 0) {
hash ^= (x >> 24);
hash &= ~x;
}
}
int result = (hash & 0x7FFFFFFF) % number;
return result;
}
六,快速排序
快速排序的步骤:
-
从数组中选出一个中枢数(pivot)
-
重新排列该数组,让数组中比该数小的数都排在该数的前面,比该数大的数都排在该数的后面。经过这次排序,该数处于其最终为止,并将原数组分为两个子数组(大于它的数组和小于它的数组),这就是分段的过程。
-
递归的排列各个子数组,直至最后整个数组排序完成。
快速排序的平均时间复杂度为O(nlogn),空间复杂度依据各种实现方式有所不同。
public int partition(int[] data, int left, int right, int pivotIndex) {
int privotValue = data[pivotIndex];
swap(data, pivotIndex, right);
int storeIndex = left;
for (int i = left; i < right; i++) {
if (data[i] <= privotValue) {
swap(data, i, storeIndex);
storeIndex = storeIndex + 1;
}
}
swap(data, storeIndex, right);
return storeIndex;
}
public void quick_sort(int[] data, int left, int right) {
if (right > left) {
int pivotIndex = left;
int pivotNewIndex = partition(data, left, right, pivotIndex);
quick_sort(data, index, pivotNewIndex - 1);
quick_sort(data, pivotNewIndex + 1, right);
}
}
七,归并排序
归并排序是一种基于比较的排序算法,在多数的实现方法中它是稳定的。归并排序可是由计算机祖师级人物——冯诺依曼提出的哦。
归并排序的过程:
-
如果数据链表的长度为0或1,则返回
-
将原始数据链表对半分成两个子链表
-
对每个子链表递归的调用合并排序进行排序
-
合并两个子链表使其成为一个排序完成的链表
归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。
public List<Integer> mergesort(List<Integer> data) {
if (data.size() <= 1) {
return data;
}
int middle = data.size() / 2;
List<Integer> left = new ArrayList<Integer>();
List<Integer> right = new ArrayList<Integer>();
for (int i = 0; i < middle; i++) {
left.add(data.get(i));
}
for (int i = middle; i < data.size(); i++) {
right.add(data.get(i));
}
left = mergesort(left);
right = mergesort(right);
List<Integer> result = merge(left, right);
return result;
}
public List<Integer> merge(List<Integer> left, List<Integer> right) {
List<Integer> result = new ArrayList<Integer>();
while (left.size() > 0 && right.size() > 0) {
if (((Integer)left.get(0)).intValue() <= ((Integer)right.get(0)).intValue()) {
result.add(left.get(0));
left.remove(0);
} else {
result.add(right.get(0));
right.remove(0);
}
}
if (left.size() > 0) {
for (Iterator<Integer> iter = left.iterator(); iter.hasNext();) {
result.add(iter.next());
}
}
if (right.size() > 0) {
for (Iterator<Integer> iter = right.iterator(); iter.hasNext();) {
result.add(iter.next());
}
}
return result;
}
八,堆排序
堆排序是一种基于比较的排序算法,它比实现的较好的快速排序慢一些,但是它的平均时间复杂度为O(nlogn),空间复杂度为O(n),它是一种in-place的算法,但是确实不稳定的排序算法。
最大堆和最小堆的定义:
根结点(亦称为堆顶)的关键字是堆里所有节点关键字中最小者的堆成为最小堆。
根结点(亦称为堆顶)的关键字是堆里所有节点关键字中最大者的堆成为最大堆。
P.S.:
堆中任一子树亦是堆。本文讨论的堆实际上是二插堆(Binary Heap),类似地可以定义k叉堆。
堆排序的过程:
-
根据输入的数据集建立一个最大堆(最小堆)
-
进行堆排序,将Root(最大值)与堆的最后一个元素交换
-
堆调整,继续维护成为最大堆
-
进行步骤2和3,直至排序完成
public void siftDown(int[] data, int start, int end) {
int root = start;
while ((2 * root + 1) <= end) {
int child = root * 2 + 1;
int (child < end && data[child] < data[child + 1]) {
child++;
}
if (data[root] < data[child]) {
swap(data, root, child);
root = child;
} else {
break;
}
}
}
这段代码是堆排序的核心,对堆中的元素进行调整。简单来说做的工作就是,即针对一个堆点,将其与它孩子中较大的那个进行比较,若大不变,若小与该孩子交换位置,若交换后该堆点(处于原先它孩子的位置)仍有孩子则继续与孩子中较大的那个进行比较,若大不变,若下与该孩子交换位置,调整直至该堆点没有孩子结束。
public void heapify(int[] data, int count) {
int start = (count - 1) /2;
while (start >= 0) {
siftDown(data, start, count - 1);
start = start - 1;
}
}
这段代码是建堆的过程,找到最后一个有孩子的堆点,对该堆点进行调整,直至调整到Root。
public void heapsort(int[] data, int count) {
heapify(data, count);
int end = count - 1;
while (end > 0) {
swap(data, 0, end);
siftDown(data, 0, --end);
}
}
这段代码解释了堆排序的过程,首先建堆,然后将Root与堆底元素交换,继而调整现有堆中Root(交换后的Root)位置,不断的调整直至遍历完整个堆。
相关推荐
1.3算法案例(2)--秦九韶算法与排序.doc
**蚁群算法与排序策略** 蚁群算法(Ant Colony Optimization, ACO)是一种模拟自然界蚂蚁寻路行为的优化算法,最初由Marco Dorigo在1992年提出。这种算法利用蚂蚁在寻找食物过程中释放的信息素来启发式地解决组合...
选择排序算法也是一种简单的排序算法,它的工作原理是通过选择最小或最大元素,并将其与第一个元素交换,以达到排序的目的。选择排序算法的时间复杂度也为O(n^2),因此它也适合小规模的数据排序。 3.插入排序算法 ...
排序算法集 排序算法集 排序算法集 排序算法集 排序算法集 排序算法集 排序算法集 排序算法集 排序算法集 排序算法集
常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结
本篇文章将详细讨论几种常见的排序算法:选择排序、冒泡排序、插入排序、合并排序以及快速排序,分析它们的算法原理、时间效率,并通过经验分析验证理论分析的准确性。 **1. 选择排序(Selection Sort)** 选择排序...
堆排序是一种高效的排序算法,通过将数组转换成堆,然后不断地将堆的根元素与最后一个元素交换,直到整个数组有序。其时间复杂度为 O(n log n)。 5. 归并排序(Merge Sort) 归并排序是一种高效的排序算法,通过将...
该程序包含7大排序算法: # sort.bubbleSort() #冒泡排序 # sort.shellSort() #希尔排序 # sort.insertionSort() #插入排序 # sort.Selectionsort1() #选择排序 # sort.heapSort() #堆排序 # sort.countSort() ...
舞动的排序算法 快速排序 通过动画演示快速排序,很好的学习,课程资源。
算法分析与设计排序算法比较 通过对各种排序算法的思想、算法的分析,探究它的使用范围以及时间复杂度和空间复杂度。 冒泡排序算法 冒泡排序算法思想简单描述:在要排序的一组数中,对当前还未排好序的范围内的...
js排序算法动态显示js排序算法动态显示js排序算法动态显示js排序算法动态显示js排序算法动态显示js排序算法动态显示js排序算法动态显示js排序算法动态显示js排序算法动态显示js排序算法动态显示js排序算法动态显示js...
十大经典排序算法堆排序详细图解(通俗易懂)十大经典排序算法堆排序详细图解(通俗易懂)十大经典排序算法堆排序详细图解(通俗易懂)十大经典排序算法堆排序详细图解(通俗易懂)十大经典排序算法堆排序详细图解...
在计算机科学领域,排序算法是数据处理中至关重要的一部分,它涉及到如何有效地重新排列一组数据,使其按照特定的顺序(如升序或降序)排列。本文将深入探讨排序算法的基本概念、常见类型以及它们在实际应用中的作用...
本篇文章主要讲解了六种排序算法的排序系统,包括插入排序、冒泡排序、选择排序、快速排序、堆排序和归并排序。该系统可以让用户选择六种排序算法中的任意一个,并输出结果。 插入排序 插入排序的主要算法思想是将...
**串行全比较排序**虽然也称为“全比较”,但与并行版本不同,它不利用并行性。在这种方法中,所有元素一次只参与一个比较,直到整个数组排序完成。C++实现时,这可能涉及更复杂的比较逻辑,而Verilog实现则可能需要...
查找与排序算法的实现和应用 查找算法是计算机科学中的一种基本算法,用于在数据结构中搜索某个特定的值或记录。常见的查找算法有顺序查找、二分法查找、快速查找等。 在顺序查找算法中,我们需要从头到尾遍历整个...
报告的标题是“中科大算法导论课程实验 常见排序算法的实现与性能比较”,指出了本实验报告的重点在于实现并比较各类常见排序算法。 #### 描述解读 描述部分指明了实验的目的和范围,要求对六种排序算法——合并...
除了直接插入排序,还有其他类型的内部排序算法,如交换排序(如快速排序)、选择排序、归并排序、基数排序以及二叉排序树排序等。每种算法都有其独特的优点和适用场景,比如快速排序在平均情况下的时间复杂度为O...
首先构造一个大顶堆(或小顶堆),然后将堆顶元素与末尾元素交换,接着对剩余元素重新调整为堆,重复此过程,直到所有元素都被排序。 这七种排序算法各有优缺点,适用场景不同。快速排序通常最快,但最坏情况下性能...
**Python语言程序设计课教程——1ADS算法与排序算法** 排序算法是计算机科学中的核心概念,特别是在编程语言如Python中,它们对于数据处理和分析至关重要。1ADS算法(可能是指"1st Approach to Data Structures",...