数组排序——待更新版

这篇博客主要介绍了数组排序的几种常见算法,包括使用函数库的sort函数进行升序排序,详细解析了归并排序的原理及代码实现,选择排序的思路和步骤,以及快速排序的方法。此外,还提及了斐波那契查找作为一种类似于二分查找的策略。
摘要由CSDN通过智能技术生成

数组排序

   获取数组长度 :   

          一般数组 :sizeof(arr)/sizeof(arr[0])

          动态数组 :arr.size();

1、函数库中的sort函数(默认升序)

#include<algorithm>//  包含头文件

sort(数组名,数组名+数组容量);

 int arr[]={2,5,9,1,4,3,6,7,8};

    sort(arr,arr+9);//数字名+需要排序的数量,可以全排,也可以部分排序,但是不可从按中间开始排序。

    for(int i=0;i<9;i++)

    {

        cout<<arr[i]<<endl;

    }

输出结果为 :1 2 3 4 5 6 7 8 9

对向量进行排序 sort(name.begin(),name.end());

     关于sort函数在我的c++收藏里面有,我觉得他写的很好。

2、归并排序(代码是复制别人的)

/*
   此程序为归并排序。
       思想为将排序的数组arr分为两个数组arr1、arr2,然后用将arr1、arr2数组中最前面的最小值放于某一数组最前面,
   在这之前arr1、arr2进行类似的排序算法,只是数组的容量不同,所以用的递归算法
   例如数组arr[]={4,3,1,2};
   arr1[]={4,3}
   arr2[]={1,2}
   对arr1排序 分成两数组   4 和 3
   3<4 所以arr1[]={3,4}
   同样的 arr2=[]={1,2}
   然后排序 : 1<3  所以arr[0]=3
   2<3   所以arr[1]=2
   然后arr[2]=3   ,arr[3]=4;   */

/*
   此程序为归并排序。
       思想为将排序的数组arr分为两个数组arr1、arr2,然后用将arr1、arr2数组中最前面的最小值放于某一数组最前面,
   在这之前arr1、arr2进行类似的排序算法,只是数组的容量不同,所以用的递归算法
   例如数组arr[]={4,3,1,2};
   arr1[]={4,3}
   arr2[]={1,2}
   对arr1排序 分成两数组   4 和 3
   3<4 所以arr1[]={3,4}
   同样的 arr2=[]={1,2}
   然后排序 : 1<3  所以arr[0]=3
   2<3   所以arr[1]=2
   然后arr[2]=3   ,arr[3]=4;   */

​​package Sort;
//归并排序
//代码是复制的
public class MergeSort {
    public static int[] mergeSort(int[] nums, int l, int h) {
        if (l == h)//如果相等 不用再分 直接返回
            return new int[] { nums[l] };

        int mid = l + (h - l) / 2;
        int[] leftArr = mergeSort(nums, l, mid); //左有序数组
        int[] rightArr = mergeSort(nums, mid + 1, h); //右有序数组
        int[] newNum = new int[leftArr.length + rightArr.length]; //新有序数组

        int m = 0, i = 0, j = 0;
        while (i < leftArr.length && j < rightArr.length) {
            newNum[m++] = leftArr[i] < rightArr[j] ? leftArr[i++] : rightArr[j++];
        }
        while (i < leftArr.length)
            newNum[m++] = leftArr[i++];
        while (j < rightArr.length)
            newNum[m++] = rightArr[j++];
        return newNum;
    }
    public static void main(String[] args) {
        int[] nums = new int[] { 9, 8, 7, 6, 5, 4, 3, 2, 10 };
        int[] newNums = mergeSort(nums, 0, nums.length - 1);
        for (int x : newNums) {
            System.out.println(x);
        }
    }
}

 3、选择排序


寻找一个数字应在数组中的位置,然后将该数字放于该位置。

             例如 数组ans[]={1  ,  5   , 8   , 2}(假设排序的一段过程,然后已经使前三个数字有序)

                         因为 2<8 所以将8的值赋ans[3]给第一次比较之后数组为 1   5   8   8

                         之后2和5比较,因为2<5 所以将5的值赋给ans[2] ,所以数组为 1   5    5     8

                        然后2和1比较,因为2>1所以2的位置应该在ans[1],将2的值赋值给ans[1] 

之后数组顺序为 1   2   5   8 

具体代码如下:

int main()
{
    int  a[10] = { 1,5,8,2 };
    for (int i = 1; i < 4; i++)
    {
        int num = a[i];
        int j = i;
        while (j > 0 && a[j - 1] >num)//切记,此处比较的对象是num,是不是a[i],因为a[i]的值可能会被修改。第i个数字之前的数字一定是有序的
        {
            a[j] = a[j - 1];
            j--;
            for (int i = 0; i < 4; i++)
                cout << a[i] << " ";
            cout << endl;
        }
        a[j] = num;
        
        
    }
    for (int i = 0; i < 4; i++)
        cout << a[i] << " ";
    cout << endl;
    return 0;
}

运行结果如下:

4、快速排序

/*
   本程序为快速排列
   快速排列与归并排列相似,都要将数组分为两个小数组,然后继续排列这两个小数组,需要用到递归。
   数组划分方法:选取第一个(区间)数组中的第一个数为关键数arr[pos],运用两边同时查询的方式然后将比该数小的数放到左边,比该数大的放到右边。
   例如:数组  5,2,1,8,3,9 ; 设置寻找i,j,分别记录寻找位置的下标,i=0(区间的起始位置,我们先假设0),j=
   关键数为5 先从右边向左寻找到小于关键数的数,然后让j等于该数下标,然后从i的位置向右寻找比关键数大的数,然后让i等于该数下标,然后交换i,j位置的数,
   然后重复该操作,直至i=j,然后swap(arr[i[,arr[pos])。
   然后对每个小组进行该操作区间分别为0 -> i,i+1 -> sizeof(arr)/sizeof(arr[0])。

需要注意的是,在一定先要从数组的最右侧向左侧寻找。因为最后需要将i,j位置上的数与关键数进行交换,如果从最左侧开始寻找的话,那么当i=j时,arr[j]可能大于关键数,然后交换的话就不能保证关键数左边的数都小于关键数。但是如果从右边开始那么j停留的位置上的数是一定小于关键数的,然后交换之后关键数左边的数一定小于等于右边的数。       
   
*/

#include <iostream>
using namespace std;
int key_pos(int a[], int from, int to)
{
    int first = from;
    int end = to;
    cout << "关键值为" << a[first] << " " ;
    cout << "对范围从"<<first<<"到"<<end<<"的数组 :";
    for (int i = first; i <= end; i++)
        cout << a[i] << " ";
    cout << "进行排序   ";
    while (from < to)
    {
        while (a[to] >= a[first] && to > from)
        {
            to--;
        }
        while (a[from] <= a[first] && to > from)
        {
            from++; 
        }
        /*cout << "to=" << to << endl;
        cout << "from=" << from << endl;*/
        swap(a[from], a[to]);
    }
    swap(a[from], a[first]);
    cout << "排序结果为 :";
    for (int i = first; i <= end; i++)
        cout << a[i] << " ";
    cout << endl;
    return from;
}
void quick_sort(int a[], int from,int to)
{
    if (from == to)
        return;
    int pos = key_pos(a, from, to);
    quick_sort(a, from, pos );
    quick_sort(a,  pos+1, to );
}
int main()
{
    int a[] = { 5,1,6,4,1,8 };
    quick_sort(a, 0, 5);
    cout << endl;
    cout << "总排序结果为 :";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    return 0;
}

5、斐波那契查找

与二分查找相似:数组有序    

mid=left+f[k-1]-1
package Search;

import java.util.Arrays;

//斐波那契查找 :离谱 为啥要搞这么多离谱的查找 不就改变计算Mid值的方法吗
public class FibonacciSearch {
    //先创建一个斐波那契数组
    public static int[] f=new int[20];
    static{//静态代码块为斐波那契数组赋值
        f[0]=1;
        f[1]=1;
        for(int i=2;i<20;i++){
            f[i]=f[i-1]+f[i-2];
        }
    }
    public static int search(int arr[],int target){
        int len=arr.length-1;
        int k=0;
        while(len>f[k]-1){//找到不小于arr长度的第一个斐波那契数
            k++;
        }
        int reallArr[]= Arrays.copyOf(arr,f[k]-1);//将arr数组中的内容拷贝到realArr中
        if(f[k]-1>len){//找到的斐波那契数大于arr.length 也就是说realArr角标的大于arr.length-1后的部分的值默认使用0赋值,但是
            //为了维持数组的有序性已经不出现arr中可能不存在的数,所以我们用arr数组中的最后一位数补齐
            Arrays.fill(reallArr,len,f[k]-1,arr[len]);
        }
        int left=0;
        while(k>0){//如果k==0说明已经遍历了完成  不存在target 直接返回-1
            //因为数组或者以后数组中的某一部分的长度是斐波那契数 ,按照斐波那契数的规律f[k]=f[k-1]+f[k-2]
            //因为角标从零开始 该部分的黄金分割点的角标 mid=left+f[k-1]-1
            int mid=left+f[k-1]-1;
            if(target>reallArr[mid]){//判断右边
                left=mid+1;
                k=k-2;
            }else if(target<reallArr[mid]){//判断左边
                k--;
            }else{
                if(mid>arr.length)
                    return arr.length-1;
                return mid;
            }
        }
        return -1;
    }
    public static void main(String[] args){
        int arr[]=new int[100];
        for (int i=0;i<arr.length;i++){
            arr[i]=i+1;
        }
        System.out.println(search(arr,-100));
        System.out.println(search(arr,0));
        System.out.println(search(arr,10));

    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值