数组排序
获取数组长度 :
一般数组 :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)); } }