常用排序查找算法c#(冒泡,插入,选择,希尔,快排,二分,堆,归并)

排序模版:

 public static bool less(int a,int b)
    {
        return a - b < 0;
    }
    public static void exch(int[] a,int i,int j)
    {
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

(1)冒泡排序
int[] arr = { 2, 3, 4, 67, 23, 99, 1 };

冒泡排序 n^2,稳定的排序算法 bubble sort
  for (int j = 0; j <= arr.Length - 1; j++)
            {
                for (int i = 0; i < arr.Length - 1 - j; i++)
                {
                    if (arr[i] > arr[i + 1])
                    {
                        int temp = arr[i];
                        arr[i] = arr[i + 1];
                        arr[i + 1] = temp;
                    }

                }
            } 

(2)插入排序
过程如图所示:
常用排序查找算法c#(冒泡,插入,选择,希尔,快排,二分,堆,归并)_第1张图片

插入排序,希尔排序是其的改良版 n^2,稳定排序
public int[] Insertion(int[] a)
    {
        int length = a.Length;
        for(int i = 1; i < length; i++)
        {
            for(int j = i; j > 0 && less(a[j], a[j - 1]); j--)
            {
                exch(a, j, j - 1);
            }
        }
        return a;
    }

(3)选择排序

选择排序 n^2 不是稳定排序
public int[] Selection(int[] a)
    {
        int length = a.Length;
        for(int i = 0; i < length; i++)
        {
            int min = i;
            for(int j = i+1; j<a.Length;j++)
            {
                if (less(a[j], a[min]))
                    min = j;
            }
            exch(a, i, min);
        }
        return a;
    }

(4)希尔排序
常用排序查找算法c#(冒泡,插入,选择,希尔,快排,二分,堆,归并)_第2张图片
常用排序查找算法c#(冒泡,插入,选择,希尔,快排,二分,堆,归并)_第3张图片

ps:分的间隔算法可以不一样

   希尔排序 nlog2n 稳定排序
public int[] shell(int[] a)
	{
		int length = a.Length;
		int h = 1;
		while (h<length/3) h = 3 * h + 1;//分好间隔
		while (h >= 1)//一直逆推,让间隔=1
		{
			for (int i = h; i < length; i++)
			{

				for (int j = i; j >= h && less(a[j], a[j - h]); j -= h)
				{
					exch(a, j, j - h);
				}

			}
			h = h / 3;
		}
		
		return a;
	}

(5)快速排序

快速排序:空间1,时间nlogn,是一种不稳定的排序算法
private static void QuickSort(int[] arr,int begin,int end){
	if(begin>=end) return;
	int pivotIndex=QuickSort_Once(arr,begin,end);
	QuickSort(arr,begin,pivotIndex-1);
	QuickSort(arr,pivotIndex+1,end);
}


private static int QuickSort_Once(int[] arr,int begin,int end){
	int pivot=arr[begin];
	int i=begin;
	int j=end;
	while(i<j){
		while(arr[j]>=pivot&&i<j)
		j--;
		arr[i]=arr[j];
		while(arr[i]<=pivot&&i<j)
		i++;
		arr[j]=arr[i];
	}
		arr[i]=pivot;
		return i;
	}
}

(6)折半查找,二分查找,时间复杂度logn。
条件:一定要有序。

public int Search_Bin(int[] arr,int key)
{
		int low=0;
		int high=arr.length-1;
		while(low<=high){
			int mid=(low+high)/2
			if(arr[mid]==key) return mid;
			else if(key<arr[mid])
				high=mid-1;
			else if(key>arr[mid])
				low=mid+1;
		}
		return 0;
		

}

(7)堆排序
时间复杂度:nlogn
不稳定排序

 /// 
    /// 对i节点做一次heapify
    /// 
    /// 数组
    /// 数组长度
    /// 从哪个节点开始
    /// 
    int[] heapify(int[] tree,int n,int i)
    {
        if (i >= n)
            return null;

        //首先计算出i序号的子节点的序号
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;
        int max = i;
        //i与两个子节点对比,找出最大的那个
        if (c1 < n && tree[c1] > tree[max])
        {
            max = c1;
        }
        if (c2 < n && tree[c2] > tree[max])
        {
            max = c2;
        }

        //如果i为最大,就不交换,否则要和最大的那个子节点交换值
        //值交换后,再对i下面的节点也做次heapify,递归出口是i
        if (max != i)
        {
            exch(tree, max, i);
            heapify(tree, n, max);
        }
        return tree;


    }
    /// 
    /// 找到最后一个节点的父节点,然后父节点依次往上都做依次heapify操作
    /// 就能构建出一个堆
    /// 
    /// 数组
    /// 数组的长度
    /// 
    int[] build_heap(int[] tree,int n)
    {
        //找到最后一个节点
        int last_node = n - 1;
        //找到最后一个节点的父节点
        int parent = (last_node - 1) / 2;
        //依次从父节点往上做heapify
        for(int i = parent; i >= 0; i--)
        {
            heapify(tree, n, i);
        }
        return tree;
    }

    /// 
    /// 堆排序
    /// 
    /// 要排序的数组
    /// 数组长度
    /// 
    int[] heapsort(int[] tree,int n)
    {
        //构建一个堆,这个堆的1个节点肯定是最大的那个
        build_heap(tree, n);
        //把最大的节点依次和第0个交换,每一次都是从第一节点做heapify
        for(int i = n - 1; i >= 0; i--)
        {
            exch(tree, 0, i);
            heapify(tree, i, 0);
        }

        return tree;
    }

    void exch(int[] arr,int i,int j)
    {
        
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        
    }

(8)归并排序 nlogn,稳定排序
常用排序查找算法c#(冒泡,插入,选择,希尔,快排,二分,堆,归并)_第4张图片

/// 
    /// 归并排序的总入口
    /// 
    /// 
    /// 
    void merge_sort(int[] arr,int n)
    {
        int[] tempArr = new int[n];
        msort(arr, tempArr, 0, n - 1);
    }

    /// 
    /// 归并排序
    /// 
    /// 数组
    /// 临时存储的排好了序的数组
    /// 指向数组的左边,即开头
    /// 指向数组的右边,即结尾
    void msort(int[] arr,int[] tempArr,int left,int right)
    {
        if (left < right)//一直到只有一个元素时停止划分
        {
            //找中间点划分
            int mid = (left + right) / 2;
            //递归划分左半区域
            msort(arr, tempArr, left, mid);
            //递归划分右半区域
            msort(arr, tempArr, mid + 1, right);
            //合并已经排序的部分
            merge(arr, tempArr, left, mid, right);

        }
    }

    /// 
    /// 合并排序
    /// 
    /// 要排序的数组
    /// 临时存储的数组
    /// 要排序的左半部分
    /// 中间点
    /// 要排序的右半部分
    void merge(int[] arr,int[] tempArr,int left,int mid,int right)
    {
        //标记左半区的第一个未排序元素
        int l_pos = left;
        //标记右半区第一个未排序元素
        int r_pos = mid + 1;
        //临时数组的元素下标
        int pos = left;

        //合并
        while (l_pos <= mid && r_pos <= right)
        {
            //如果左半区第一个元素更小就把左半区第一个元素放入
            //临时的数组中,如果右半区的更小,就放入右半区的第一个元素
            //然后更小的那个半区的指针l_pos往后挪
            if (arr[l_pos] < arr[r_pos])
            {
                tempArr[pos] = arr[l_pos];
                pos++;
                l_pos++;
            }
            else
            {
                tempArr[pos] = arr[r_pos];
                pos++;
                r_pos++;
            }
        }

        //如果左半区还有剩
        while (l_pos <= mid)
        {
            tempArr[pos] = arr[l_pos];
            pos++;
            l_pos++;
        }
        //如果右半区还有剩
        while (r_pos <= right)
        {
            tempArr[pos] = arr[r_pos];
            pos++;
            r_pos++;
        }

        //把临时数组拷贝到之前的数组
        while (left <= right)
        {
            arr[left] = tempArr[left];
            left++;
        }
    }
    

你可能感兴趣的:(数据结构与算法,算法,排序算法,快速排序,插入排序,algorithm)