这三天把基本算法学了一遍,现在做下总结,方便以后查看。
八种排序算法分别是:直接插入排序,希尔排序,冒泡排序,选择排序,堆排序,快速排序,归并排序,基数排序
1.直接插入排序:数据集排序比较好的情况下使用
思路:第i个元素A,如果比前面的数字小,则前面的数字向后移动移位,A继续向前比较,直到不满足条件
private static void insertSort(int[] data) {
for (int i = 1; i < data.length; i++) {
int j = i - 1;
int temp = data[i];
for (; j > 0 && temp < data[j]; j–) {
data[j + 1] = data[j];
}
data[j + 1] = temp;
}
}
2.希尔排序,因为如果数字结合排序很乱,直接插入排序效率会比较低,这是在直接插入排序的改进.
private static void shellSort(int[] data2) {
int pace = data.length;
int k;
int temp;
while (true) {
// 每一次步长减半
pace = pace / 2;
for (int i = 0; i < pace; i++) {
for (int j = pace; j < data.length; j += pace) {
k = j - pace;
temp = data[j];
//如果j位这个数比data[j-pace]小,data[j-pace]的数向后移动
for (; k > 0 && temp < data[k]; k -= pace) {
data[k + pace] = data[k];
}
data[k + pace] = temp;
}
}
//当步长为1时排序完成
if (pace == 1) {
return;
}
}
}
3.冒泡排序,代码实现最简单的排序算法,不过效率最低
private static void bubbleSort(int[] data2) {
int[] data = Arrays.copyOf(data2, data2.length);
startTime = System.nanoTime();
int len = data.length;
int temp;
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
// 如果前面的数字大于后面的数字,就交换,每次循环,相当于把当前最大的数字移动到最后面
if (data[j] > data[j + 1]) {
temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
}
4.简单选择排序,实现思路跟冒泡排序差不多
private static void selectSort(int[] data2) {
int j;
int temp;
int position;
for (int i = 0; i < data.length; i++) {
j = i + 1;
temp = data[i];
position = i;
for (; j < data.length; j++) {
//如果当前的数小于第i数交换,就交换
if (data[j] < temp) {
temp = data[j];
position = j;
}
}
data[position] = data[i];
data[i] = temp;
}
}
5.堆排序 测试时效率最高的排序算法(网上都说快速排序效率最高)
private static int[] heapSort(int[] data2) {
// 建最小堆
buidMinHeap(data);
for (int i = 0; i < data.length; i++) {
int last = data.length - i - 1;
// 下标为0的数跟last下标的数交换
int temp = data[0];
data[0] = data[last];
data[last] = temp;
minHeapDown(data, 0, last - 1);// 交换后的数字不在改变
}
return data;
// show(data);
}
// 父节点为 (i-1)/2
private static void buidMinHeap(int[] data) {
int last = data.length - 1;
// 最后一个父节点下标
for (int f = (last - 1) / 2; f >= 0; f--) {
minHeapDown(data, f, last);
}
}
/**
* 最小堆,下沉
*
* @param data
* @param f 父节点下标
* @param last 数组最后一个下标
*/
private static void minHeapDown(int[] data, int f, int last) {
int son = f * 2 + 1;
int temp = data[f];
// 保存当前的父节点下标
int k = f;
// 如果有子节点
while (son <= last) {
// 判断左右子节点大小
if (son + 1 <= last && data[son] > data[son + 1]) {
// 若果右节点存在并且比左节点小,父节点与右节点进行比较
son++;
}
// 如果父节点比小的子节点小或等于,不用调整位置
if (temp <= data[son]) {
break;
}
// 父节点大于子节点,需要交换的情况
data[k] = data[son];
k = son;
son = 2 * k + 1;
}
data[(son - 1) / 2] = temp;
}
6.快速排序 参考视频 http://www.iqiyi.com/v_19rrhzyeqs.html
private static void quickSort(int[] data2) {
if (data.length > 0) {
_quickSortStart(data, 0, data.length - 1);
}
// show(data);
}
private static void _quickSortStart(int[] data, int low, int high) {
if (low < high) {
int middle = getMiddle(data, low, high);
// 对低位部分进行排序
_quickSortStart(data, low, middle - 1);
// 对高位部分进行排序
_quickSortStart(data, middle + 1, high);
}
}
private static int getMiddle(int[] data, int low, int high) {
int temp = data[low];
while (low < high) {
while (low < high && temp <= data[high]) {
high--;
}
data[low] = data[high];
while (low < high && data[low] <= temp) {
low++;
}
data[high] = data[low];
data[low] = temp;
}
// show(data);
return low;
}
7.归并排序
private static void mergeSort(int[] data2){
int len=data.length;
if(len>1){
_mergeSort(data,0,len-1);
}
//show(data);
}
private static void _mergeSort(int[] data, int l, int r) {
if(l==r){
return;
}
int m=(r+l)/2;
_mergeSort(data, l, m);
_mergeSort(data, m+1, r);
merge(data, l, m+1, r);
}
private static void merge(int[] data,int l,int m,int r){
int[]left=Arrays.copyOfRange(data,l,m );
int[]right=Arrays.copyOfRange(data, m, r+1);
int i=0;
int j=0;
while(i<left.length && j<right.length){
if(left[i]<right[j]){
data[l]=left[i];
i++;
}else{
data[l]=right[j];
j++;
}
l++;
}
while(i<left.length){
data[l]=left[i];
l++;
i++;
}
while(j<right.length){
data[l]=right[j];
l++;
j++;
}
}
8.基数排序
private static void radixSort(int[]data2){
//获得最大值
int max=0;
for(int d:data){
if(d>max){
max=d;
}
}
//计算数字的位数
int order=1;
while(max>0){
max/=10;
order++;
}
List<List> datas=new ArrayList<List>();
//创建10个集合
for(int i=0;i<10;i++){
List<Integer> queue=new ArrayList<>();
datas.add(queue);
}
//进行order次分配和收集
for(int i=0;i<order;i++){
for(int j=0;j<data.length;j++){
//当前位上的数字,比如百位,十位,个位上的数字
int x = data[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
List<Integer> list=datas.get(x);
list.add(data[j]);
datas.set(x, list);
}
int k=0;
//对一次排序之后进行收集
for(List que:datas){
while(que.size()>0){
data[k]=(int) que.get(0);
que.remove(0);
k++;
}
}
}
//show(data);
}