数组排序问题是java工程师面试过程中很常见的问题之一,也是java程序员必备的知识。本文总结了用java实现常用的排序算法。
注:数组从小到大排序
1. 冒泡排序
特点:效率低,实现简单,容易理解
思想:每一次遍历,将待排序中最大的元素移到最后,剩下的为新的待排序序列,重复上述步骤直至排序完所有元素。
代码实现:
public void bubbleSort(int array[]){
int t = 0;
for(int i = 0; i < array.length - 1; i++){
for(int j = 0; j < length.length - 1 - i; j++){
if(array[j] > array[j + 1]){
t = array[j];
array[j] = array[j + 1];
array[j + 1] = t;
}
}
}
}
2.选择排序
特点:效率低,实现简单,容易理解
思想:每一次遍历,从待排序中选择一个最小的元素放到已排序序列的末尾,剩下的为待排序序列,重复上述步骤直至排序完所有元素。
代码实现:
public void selectSort(int array[]) {
int t = 0;
for (int i = 0; i < array.length - 1; i++){
int index=i;
for (int j = i + 1; j < array.length; j++){
if (array[index] > array[j])
index=j;
}
if(index!=i){
t = array[i];
array[i] = array[index];
array[index] = t;
}
}
}
3. 插入排序
特点:效率低,容易实现,容易理解。
思想:将数组分为两部分,将后一部分的元素逐一与前部分进行比较,如果前部分元素比array[i]小,就将前部分元素往后移动。当没有比array[i]小的元素,即是合理位置,在此位置插入array[i]
代码实现:
public void insertionSort(int array[]) {
int i, j, t = 0;
for (i = 1; i < array.length; i++) {
if(a[i]<a[i-1]){
t = array[i];
for (j = i - 1; j >= 0 && t < array[j]; j--)
array[j + 1] = array[j];
//插入array[i]
array[j + 1] = t;
}
}
}
4.快速排序
特点:高效,时间复杂度为NlogN。
思想:采用分治法的思想,首先设置一个轴值pivot(一般为第一个元素),然后以这个轴值为划分基准,将待排序序列分成比pivot大和比pivot小的两部分,接下来对划分完的子序列进行快速排序直到子序列为一个元素为止。
代码实现:
public void quickSort(int array[], int low, int high) {// 传入low=0,high=array.length-1;
int pivot, p_pos, i, t;// pivot->位索引;p_pos->轴值。
if (low < high) {
p_pos = low;
pivot = array[p_pos];
for (i = low + 1; i <= high; i++)
if (array[i] > pivot) {
p_pos++;
t = array[p_pos];
array[p_pos] = array[i];
array[i] = t;
}
t = array[low];
array[low] = array[p_pos];
array[p_pos] = t;
// 分而治之
quickSort(array, low, p_pos - 1);// 排序左半部分
quickSort(array, p_pos + 1, high);// 排序右半部分
}
}
5.堆排序
思想:利用堆的性质进行排序
堆分为两类:
1、最大堆(大顶堆):堆的每个父节点都大于其孩子节点;
2、最小堆(小顶堆):堆的每个父节点都小于其孩子节点;
堆的存储:
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。
堆的第一个元素要么是最大值(大顶堆),要么是最小值(小顶堆),这样在排序的时候(假设共n个节点),直接将第一个元素和最后一个元素进行交换,然后从第一个元素开始进行向下调整至第n-1个元素。所以,如果需要升序,就建一个大堆,需要降序,就建一个小堆。
堆排序的步骤分为三步:
1、建堆(升序建大堆,降序建小堆);
2、交换数据;
3、向下调整。
代码实现:
void AdjustDown(int arr[], int i, int n)
{
int j = i * 2 + 1;//子节点
while (j<n)
{
if (j+1<n && arr[j] > arr[j + 1])//子节点中找较小的
{
j++;
}
if (arr[i] < arr[j])
{
break;
}
swap(arr[i],arr[j]);
i = j;
j = i * 2 + 1;
}
}
void MakeHeap(int arr[], int n)//建堆
{
int i = 0;
for (i = n / 2 - 1; i >= 0; i--)//((n-1)*2)+1 =n/2-1
{
AdjustDown(arr, i, n);
}
}
void HeapSort(int arr[],int len)
{
int i = 0;
MakeHeap(arr, len);
for (i = len - 1; i >= 0; i--)
{
swap(arr[i], arr[0]);
AdjustDown(arr, 0, i);
}
}