欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

各种排序,一网打尽!

程序员文章站 2022-06-01 10:18:16
...

说到排序,大家都不陌生
有点编程基础的人都懂哈哈
各种各样的排序,你懂的程度有多少呢
排序之间又有什么关联了
这篇文章我谈谈我的理解

简单排序!

Comparable接口

比如学生的排序,按照年龄或者身高
实现Comparable接口的类进行的排序
这里我图省事,写的很简单,说明问题就行,一看便懂!

public class Student implements Comparable<Student>{
	public int age;
	@Override
	public int compareTo(Student s){
		return this.age-s.age;
	}
}

@Test
public Comparale getMax(Compareble c1,Comparable c2){
	int cmp=c1.compareTo(c2);
	if(cmp>0){return c1;}
	else{return c2;}
}

冒泡排序

1.比较相邻元素,要是后面比前面小,则交换位置
2.从开始到末尾,每一组都这样比对
熟悉的配方!

def bubble(l):
    for i in range(len(l)):
        for j in range(len(l)-i-1):
            if l[j] > l[j+1]:
                l[j], l[j+1] = l[j+1], l[j]
l = [9, 8, 7, 2, 3]
bubble(l)
print(l)

想象一下这个过程,冒泡,每一次循环,最大的数就冒到最后了
j 的范围为什么是len(l)-1-i?
因为每一次循环之后,最后那个数已经最大了,不需要再比对他和她前面的数 的大小了!
比较的次数为:
(N-1)+(N-2)+(N-3)+…+2+1=((N-1)+1)(N-1)/2=N^2/2-N/2;
交换的次数为:
(N-1)+(N-2)+(N-3)+…+2+1=((N-1)+1)
(N-1)/2=N^2/2-N/2;
时间复杂度为O(N^2).

选择排序

每次排序,假定第一个是最小,然后遍历,如果有比当前小的,就记下他的位置,遍历完后交换
交换完后再遍历,上一层第一个已经不用处理了,所以第一个其实时这一层的第二个。。。

def selectSort(l):
    for i in range(len(l)):
        minindex=i
        for j in range(i+1,len(l)):
            if l[j]<l[minindex]:
                minindex=j
        if i!=minindex:
            l[i],l[minindex]=l[minindex],l[i]
    
    return l

比较的次数为:
(N-1)+(N-2)+(N-3)+…+2+1=((N-1)+1)*(N-1)/2=N^2/2-N/2;
交换的次数为:
N-1;
时间复杂度为O(N^2).
其实这里有一个优化,就是 i 的循环次数,考虑一下

插入排序

所有元素分为排好序的和未排序的,每次从未排序的元素中找第一个元素,插入到排序组中

def insertsort(arr):
    for i in range(len(arr)):
        for j in range(i,0,-1):
            if arr[j-1]>arr[j]:
                arr[j-1],arr[j]=arr[j],arr[j-1]
    return arr

l=insertsort([9,8,7,2,1])
print(l)

比较的次数为:
(N-1)+(N-2)+(N-3)+…+2+1=((N-1)+1)(N-1)/2=N^2/2-N/2;
交换的次数为:
(N-1)+(N-2)+(N-3)+…+2+1=((N-1)+1)
(N-1)/2=N^2/2-N/2;
时间复杂度为O(N^2).

高级排序

希尔排序

是插入排序的进阶版本,在插入排序中,我们对比未排序的元素在排序元素组中的位置的时候,每次从最后往前一个一个比较,
所以新的改进是,每次跳跃着比较,把步进从1可以变大一点,这样会提高效率

def shellsort(l):
    h=1
    while(h<len(l)/2):
        h=2*h+1
    while(h>=1):
        for i in range(h,len(l)):
            for j in range(i,h-1,-1):
                if l[j-h]>l[j]:
                    l[j-h],l[j]=l[j],l[j-h]

        h=int(h/2)
    return l

l=shellsort([9,8,7,4,6])
print(l)

选定一个gap,然后以这个gap划分组,每组两个成员,进行插入排序
每一轮使得gap减小为一半,直到为1.

归并排序

利用递归的思想
1.尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是1为止。
2.将相邻的两个子组进行合并成一个有序的大组;
3.不断的重复步骤2,直到最终只有一个组为止。

class mergesort(object):

    def merge(self, l, lo, hi):

        mid = int((lo+hi)/2)
        left = []
        right = []
        for i in range(lo, mid+1):
            left.append(l[i])
        for i in range(mid+1, hi+1):
            right.append(l[i])

        p1 = 0
        p2 = 0
        i = lo
        while p1 < len(left) and p2 < len(right):
            if left[p1] < right[p2]:
                l[i] = left[p1]
                i += 1
                p1 += 1
            else:
                l[i] = right[p2]
                i += 1
                p2 += 1
        while p1 < len(left):
            l[i] = left[p1]
            i += 1
            p1 += 1
        while p2 < len(right):
            l[i] = right[p2]
            i += 1
            p2 += 1

    def sort(self, l, lo, hi):
        if lo == hi:
            return
        mid = int((lo+hi)/2)
        self.sort(l, lo, mid)
        self.sort(l, mid+1, hi)
        self.merge(l, lo, hi)

各种排序,一网打尽!

快速排序

1.首先设定一个分界值,通过该分界值将数组分成左右两部分;
2.将大于或等于分界值的数据放到到数组右边,小于分界值的数据放到数组的左边。此时左边部分中各元素都小于
或等于分界值,而右边部分中各元素都大于或等于分界值;
3.然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两
部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
4.重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当
左侧和右侧两个部分的数据排完序后,整个数组的排序也就完成了。

def sort(arr, lo, hi):
    if hi <= lo:
        return
    part = partition(arr, lo, hi)
    #print(part)
    sort(arr, lo, part-1)
    sort(arr, part+1, hi)


def partition(arr, lo, hi):
    left = lo+1
    right = hi
    key = arr[lo]
    while True:
        while key < arr[right]:
            right -= 1
            if right == lo:
                break
        while key > arr[left]:
            left += 1
            if left == hi:
                break
        if left >= right:
            break
        else:
            arr[left], arr[right] = arr[right], arr[left]
    arr[lo], arr[right] = arr[right], arr[lo]
    #print(arr)
    return right

各种排序,一网打尽!

堆排序

对构造好的堆,我们只需要做类似于堆的删除操作,就可以完成排序。
1.将堆顶元素和堆中最后一个元素交换位置;
2.通过对堆顶元素下沉调整堆,把最大的元素放到堆顶(此时最后一个元素不参与堆的调整,因为最大的数据已经到了数组的最右边)
3.重复1~2步骤,直到堆中剩最后一个元素。

public class HeapSort {
    private static boolean less(Comparable[] heap, int i, int j) {
        return heap[i].compareTo(heap[j]) < 0;
    }

    private static void exch(Comparable[] heap, int i, int j) {
        Comparable tmp = heap[i];
        heap[i] = heap[j];
        heap[j] = tmp;
    }

    private static void createHeap(Comparable[] source, Comparable[] heap) {
        System.arraycopy(source, 0, heap, 1, source.length);
        for (int i = (heap.length) / 2; i > 0; i--) {
            sink(heap,i,heap.length-1);
        }
    }

    private static void sort(Comparable[] source){
        Comparable[] heap = new Comparable[source.length + 1];
        createHeap(source,heap);
        int N=heap.length-1;
        while (N!=1){
            exch(heap,1,N);
            N--;
            sink(heap,1,N);
        }
        System.arraycopy(heap,1,source,0, source.length);
    }

    private static void sink(Comparable[] heap, int target, int range) {
        while (2*target<=range){
            int max;
            if(2*target+1<=range){
                if(less(heap,2*target,2*target+1)){
                    max=2*target+1;
                }else {
                    max=2*target;
                }
            }else {
                max=2*target;
            }

            if(!less(heap,target,max)){
                break;
            }
            exch(heap,target,max);
            target=max;
        }
    }

    public static void main(String[] args) {
        String[] arr={"s","o","d","r","b"};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

上一篇: 小白求教!

下一篇: php文件下载