萌新的数据结构与算法1 排序算法

快速排序

    /// <summary>
    /// 快速排序
    /// 快速排序的原理是把数组中的一个数看做中间数,从右到左找一个比中间数大的数字,将该数字放在最左,然后缩小右的范围为右-1
    /// 然后从左到右找一个比中间数大的数字,放在最右,然后缩小左的范围为左+1,直到左右范围相等
    /// 此时中间数左边的数字都比中间数小,右边的数字都比中间数大,我们在本次方法中确定了一个中间数的位置
    /// 中间数将数组划分成了 (0,中间数-1) 中间数 (中间数+1,lenth-1)3个部分,对新划分的两个区域递归调用快速排序的方法
    /// 所有中间数都确定的时候 数组就完成了排序
    /// </summary>
    /// <param name="arrays">需要排序的数组</param>
    /// <param name="startIndex">本次排序范围的起始</param>
    /// <param name="endIndex">本次排序范围的终止</param>
    void quickSort(int[] arrays,int startIndex,int endIndex) {
        if (arrays==null || startIndex>=endIndex)
        {
            return;
        }
        //baseInt是本次假定的中间数
        //中间数当然是位置越趋于中间,效率越高。本次假设不知道数组的规律,默认取第一个数字看做中间数
        //如果数组有规律的话 可以想办法让中间数更接近中间 达到一些优化效果
        int baseInt = arrays[startIndex];
        int tempLeft = startIndex;//数组左下标
        int tempRight = endIndex;//数组右下标
        while (tempLeft < tempRight)
        {
            while (tempLeft < tempRight && arrays[tempRight] >= baseInt)
            {
                tempRight--;
            }
            arrays[tempLeft] = arrays[tempRight];
            while (tempLeft < tempRight && arrays[tempLeft] <= baseInt)
            {
                tempLeft++;
            }
            arrays[tempRight] = arrays[tempLeft];
        }
        arrays[tempLeft] = baseInt;
        quickSort(arrays, startIndex, tempLeft - 1);
        quickSort(arrays, tempLeft + 1, endIndex);
    }

插入排序

    /// <summary>
    /// 插入排序的原理是 将一个乱序数组 依次插入到有序的数组中
    /// 默认有序数组是array第一项 将array第二项起依次找到该元素在有序数组中的位置 并插入
    /// </summary>
    /// <param name="array"></param>
    void InsertSort(int[] array) {
        //因为第一个数直接插入不需要计算 所以i从1开始
        for (int i = 1; i < array.Length; i++)
        {
            //移动过程会破坏数组顺序 先保存当前要插入的数字
            int temp = array[i];
            //要进行从后向前i-1次循环
            int j = i - 1;
            while (j >= 0 && array[j] > temp) 
            {
                //如果当前数字比当前要插入的数字大 向右移动
                array[j + 1] = array[j];
                j--;
            }
            //下一项就是本次该插入的位置
            array[j + 1] = temp;
        }
    }

简化版

把当前要插入的数字,用交换的方式代替原来移动的方式
代码简洁很多

/// <summary>
    /// 插入排序
    /// </summary>
    /// <param name="array"></param>
    void InsertSort2(int[] array) {
        for (int i = 1; i < array.Length; i++)
        {
            for (int j = i-1; j>=0 && array[j]>array[j+1]; j--)
            {
                int temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }

选择排序

/// <summary>
    /// 选择排序 遍历数组寻找最小值
    /// 将最小值与最前项交换
    /// 缩小范围 重复上一步
    /// </summary>
    /// <param name="array"></param>
    void SelectSort(int[] array) {
        //依次将最小数放置数组 最后一个数字一定是最大的 所以减少一次循环
        for (int i = 0; i < array.Length-1; i++)
        {
            int minIndex=i;//最小数的小标 默认为本次循环的起始点
            //从i开始找最小数 前面已经排好了
            for (int j = i; j < array.Length; j++)
            {
                if (array[j]<array[minIndex])
                {
                    minIndex = j;
                }
            }
            //如果最小数不在当前位置 则交换最小数到当前位置
            if (i!=minIndex)
            {
                int temp = array[i];
                array[i] = array[minIndex];
                array[minIndex] = temp;
            }
        }
    }

冒泡排序

/// <summary>
    /// 冒泡排序
    /// </summary>
    /// <param name="array"></param>
    void BubleSort(int[] array) {
        //最后一个数字不需要计算了
        for (int i = 0; i < array.Length-1; i++)
        {
            //剩余的数字 左右对比 左边>右边则交换
            //第一次循环后 最右边一定是最大值
            //缩小范围重复此过程
            for (int j = 0; j < array.Length-1-i; j++)
            {
                if (array[j]>array[j+1])
                {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }

归并排序

/// <summary>
    /// 归并排序
    /// 将数组平均划分成两部分,【递归此方法】,直到每个部分只有一个数字
    /// 递归划分后执行以下逻辑
    /// 两部分从左到右对比,把小的数字放在辅助数组前面
    /// 直到两个部分没有数字
    /// 将辅助数组中的结果赋值到排序数组里
    /// </summary>
    /// <param name="array">需要排序的数组</param>
    /// <param name="array1">辅助数组</param>
    /// <param name="startIndex">当前左下标</param>
    /// <param name="endIndex">当前右下标</param>
    void MergeSort(int[] array, int[] array1, int startIndex, int endIndex)
    {
        if (startIndex>=endIndex)
        {
            return;
        }
        //计算中间下标
        int middle = (startIndex + endIndex) / 2;
        //分治 将数组分为0,middle  与 middle+1,length-1 两部分
        MergeSort(array, array1, startIndex, middle);
        MergeSort(array, array1, middle + 1, endIndex);
        int left = startIndex;//左半区间的左下标
        int left1 = middle+1;//右半区间的左下标
        int left2 = startIndex;//辅助数组的左下标
        //左区间左下标不超过middle , 右区间左下标不超过endIndex
        while (left <= middle || left1 <= endIndex) 
        {
            //从分割开的两个区域中 分别取第一个数字进行比较 小的数字放入辅助数组中 并缩小范围
            //left1>endIndex时array[left1]已经越界了,加入这个判断避免执行 array[left]<array[left1]
            if (left1 > endIndex || array[left] < array[left1])
                array1[left2++] = array[left++];
            else
                array1[left2++] = array[left1++];
        }
        //将结果赋给array 保存本次结果
        for (left = startIndex; left <= endIndex; left++)
            array[left] = array1[left];
    }

希尔排序

/// <summary>
    /// 希尔排序
    /// 类似归并排序 将数组划分为间隔为2的组 对每一组进行排序
    /// 逐渐增加间隔 最后整个数组只有一组时 排序结束
    /// </summary>
    /// <param name="a"></param>
    /// <param name="n"></param>
    void ShellSort(int[] a)
    {
        //将原始数组除以2的数量作为分组的数量,做一次排序,重复到group只有一组
        //group也是各个组之间成员的间隔
        for (int group = a.Length / 2; group >= 1; group /= 2)
        {
            //把每个分组的第一个数字看做已排序 从a[group]开始进行插入排序
            for (int i = group; i < a.Length; i++)
            {
                //简化版的插入排序 对组内成员进行
                for (int j = i-group; j >=0 && a[j]>a[j+group] ; j-=group)
                {
                    int temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }   
            }
        }
    }

堆排序

   /// <summary>
    /// 堆排序
    /// 堆排序涉及完全二叉树的特性,第一次接触的萌新要补补课
    /// 堆排序把数组做成大根堆,然后把根与最小叶节点交换 , 然后缩小范围
    ///  对剩余的二叉树继续调整为大根堆,然后首尾交换,最后得到排序后的数组
    /// </summary>
    /// <param name="array"></param>
    void HeapSort(int[] array)
    {
        //从右向左 从下到上 遍历非叶节点
        for (int i = array.Length / 2 - 1; i >= 0; i--)
        {
            AdjustHeap(array, i, array.Length-1);
        }
        //交换出最大数字,调成剩余的树
        for (int i = array.Length - 1; i > 0; i--)
        {
            int temp = array[0];
            array[0] = array[i];
            array[i] = temp;
            AdjustHeap(array, 0, i-1);
        }
    }
    /// <summary>
    /// 调整
    /// </summary>
    /// <param name="array"></param>
    /// <param name="startIndex">根下标</param>
    /// <param name="endIndex">最后一个叶子下标</param>
    void AdjustHeap(int[] array, int startIndex, int endIndex)
    {
        //保存根节点值
        int temp = array[startIndex];
        //从左树开始计算
        for (int i = startIndex * 2 + 1; i <= endIndex; i = i * 2 + 1)
        {
            //左树小于右树
            if (i + 1 < endIndex && array[i] < array[i + 1])
            {
                i++;//i指向右树
            }
            //以下是一个移动的方式 将temp插入
            //当前节点大于最初的根节点
            if (array[i] > temp)
            {
                //移动的方式排序
                array[startIndex] = array[i];
                //调整根位置
                startIndex = i;
            }
            //没有调整 子节点叶不需要调整了
            else
            {
                break;
            }
        }
        //将最初根节点的值插入
        array[startIndex] = temp;
    }

lua版

最近在熟悉lua,顺手用lua写了一遍加强记忆,原理和上面一样就不赘述了。

--冒泡排序
function bubleSort(array)
	for	i=1,#array-1 do
		for j=1,#array-i do
			if array[j]>array[j+1] then
				array[j],array[j+1]=array[j+1],array[j];
			end
		end
	end
end
--插入排序
function insertSort(array)
	for i=2,#array do
		for j=i,2,-1 do
			if array[j]<array[j-1] then
				array[j],array[j-1]=array[j-1],array[j];
			end
		end
	end
end
--选择排序
function selectSort(array)
	for i=1,#array do
		local min=i;
		for j=i,#array do
			if array[j]<array[min] then
				min=j;
			end
		end
		if i~=min then
			array[i],array[min]=array[min],array[i];
		end
	end
end
--快速排序
function quickSort(array,startI,endI)
	if startI>=endI then
		return;
	end
	local baseInt=array[startI];
	local leftTemp=startI;
	local rightTemp=endI;
	while (leftTemp<rightTemp) do
		while (leftTemp<rightTemp and array[rightTemp]>=baseInt) do
			rightTemp=rightTemp-1;
		end
		array[leftTemp]=array[rightTemp];
		while (leftTemp<rightTemp and array[leftTemp]<=baseInt) do
			leftTemp=leftTemp+1;
		end
		array[rightTemp]=array[leftTemp];
	end
	array[leftTemp]=baseInt;
	quickSort(array,startI,leftTemp-1);
	quickSort(array,leftTemp+1,endI);
end
--希尔排序 lua相除得到的是浮点型 坑 自己取整
function shellSort(array)
	local i=math.modf(#array/2);
	while(i>=1) do
		for j=i+1,#array do
			local k=j;
			while(k-i>=1) do
				if (array[k]<array[k-i]) then
					array[k],array[k-i]=array[k-i],array[k];
				end
				k=k-i;
			end
		end
		i=math.modf(i/2);
	end
end
--归并排序
function mergeSort(array,startI,endI,arrayTemp)
	if array==nil or startI >= endI then
		return;
	end
	local middle=math.modf((startI+endI)/2);
	local leftTemp=startI;
	local leftTemp1=middle+1;
	local leftTemp2=startI;
	mergeSort(array,startI,middle,arrayTemp);
	mergeSort(array,leftTemp1,endI,arrayTemp);
	while (leftTemp<=middle or leftTemp1<=endI) do
		if leftTemp1>endI or array[leftTemp]<array[leftTemp1] then
			arrayTemp[leftTemp2]=array[leftTemp];
			leftTemp=leftTemp+1;
			leftTemp2=leftTemp2+1;
		else
			arrayTemp[leftTemp2]=array[leftTemp1];
			leftTemp1=leftTemp1+1;
			leftTemp2=leftTemp2+1;
		end
	end
	for i=startI,endI do
		array[i]=arrayTemp[i];
	end
end
--堆排序
function heapSort(array)
	funcHeapSort=function(array,startI,endI)
					local i=startI*2;
					local temp=array[startI];
					while(i<=endI) do
						if i+1<=endI and array[i+1]>array[i] then
							i=i+1;
						end
						if array[i]>temp then
							array[startI]=array[i];
							startI=i;
						else
							break;
						end
						i=i*2;
					end
					array[startI]=temp;
				end
	for i=math.modf(#array/2),1,-1 do
		funcHeapSort(array,i,#array);
	end
	for i=#array,2,-1 do
		array[1],array[i]=array[i],array[1];
		funcHeapSort(array,1,i-1);
	end
end
--二分查找法
function binarySearch(array,target)
	if array==nil then
		return;
	end
	local startI=1;
	local endI=#array;
	while (startI<endI) do
		local middle=math.modf((startI+endI)/2);
		if target<array[middle] then
			endI=middle-1;
		elseif target>array[middle] then
			startI=middle+1;
		else
			print("found it");
			return;
		end
	end
	print("not found");
end

猜你喜欢

转载自blog.csdn.net/qq_29799917/article/details/89074246
今日推荐