十种常用算法解析

一.常用算法分类

   1.非线性时间

          比较类排序 :快速排序和冒泡排序

          插入类排序 :简单插入排序和希尔排序

          选择类排序 :简单选择排序和堆排序

          归并排序 :二路归并排序和多路归并排序

   2.线性时间

          非比较类排序 :计数排序、基数排序、桶排序

二.算法复杂度

    

三.算法实现

  1.冒泡排序原理

       从数组中第一个数开始,依次遍历数组中的每一个数,通过相邻比较交换,每一轮循环下来找出剩余未排序数的中的最大数并”冒泡”至数列的顶端。

void bubbleSort(int n){
	int i,j;
	for(i=1;i<=n;i++){        //两重循环依次遍历比较     
		for(j=1;j<n;j++){
			if(a[j]>a[j+1]){
				int t = a[j];
				a[j] = a[j+1];
				a[j+1] = t;
			}
		}
	}
}

     2.快速排序原理
        1.找一个基准数,从后向前找,直到遇到第一个比它小的数;从前往后找,直到遇到第一个比它大的数,将两个数交换位置 
        2.依次遍历直到i和j相遇
        3.将基准数与标记为i的数交换位置,至此数组完成第一次遍历,以基准数为中心,左边的都比它小,后边的都比它大
        4.对左右两组数组进行递归遍历
        5.当左右标记相等时,标志着排序完成 

void quickSort(int left,int right){
	int i,j,temp;
	if(left > right)
		return;
	temp = a[left];            //作为基准数
	i = left;
	j = right;
	while(i!=j){
		while(a[j] >= temp&&i < j){               //从右向左依次遍历
			j--;
		}
		while(a[i] <= temp&&i < j){              //从左向右依次遍历
			i++;
		}
		if(i<j){                                 //交换获取的元素
			int t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
	}
	a[left] = a[i];
	a[i] = temp;
	quickSort(left,i-1);             //递归遍历数组
	quickSort(i+1,right); 
}

3.    简单插入排序原理

    1.从第一个元素开始,该元素可以认为已经被排序;
    2.取出下一个元素,在已经排序的元素序列中从后向前扫描;
    3.如果该元素(已排序)大于新元素,将该元素移到下一位置;
    4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
    5.将新元素插入到该位置后;
    6.如果新元素大于该元素(已排序),则新元素就在该位置 ;
    7.重复步骤2~5;

void insertionSort(int n){
	int temp;
	for(int i=2;i<=n;i++){
		int j = i-1;
		temp = a[i];
		while(j>=1&&a[j]>temp){
			a[j+1] = a[j];
			j--;
		}
		a[j+1] = temp;
	}
}

4.希尔排序原理:
    Shell排序法是对相邻指定距离(称为增量)的元素进行比较,并不断把增量缩小至1,完成排序。
    1.一般初始增量是len/2,分为len/2组,每组两个元素,用插入排序比较 
    2.将增量/2;分为len/4组,每组元素用插入排序比较
    3.直至增量为1,变为一趟直接插入排序完成整个排序过程 

void shellSort(int a[],int n){
	for(int gap = n/2;gap>=1;gap/=2){
		for(int i=gap;i<=n;i++){
			int j=i-gap;
			int temp = a[i];
			while(j>=1&&temp<a[j]){
				a[j+gap] = a[j];
				j -= gap;
			}
			if((j+gap) !=i){
				a[j+gap] = temp;
			}
		}
	}
}

5.简单选择排序原理:
    1.取第一个数作为基准数,它与剩下所有数比较,得到最小数的标记
    2.最小数与第一个数交换位置,最小数来到应该到的位置
    3.依次重复n次 

void selectSort(int n){
	int i,j,k;
	for(i=1;i<=n;i++){
		k=i;
		for(j=i+1;j<=n;j++){
			if(a[j]<a[k]){
				k=j;
			}
		}
		if(i!=k){
			int t=a[i];
			a[i]=a[k];
			a[k]=t;
		}
	}
}

6.堆排序原理:
    1.将待排序序列构造成一个大顶堆(升序),然后堆顶就是整个序列的最大值与数组尾的元素交换
    2.将剩下n-1个元素重复执行
    3.得到有序序列 
    
    从最后一个非叶子结点开始(arr.length-1),即左叶子节点先与右叶节点比较
    得到的大的元素与其父节点比较,知道根节点,这样完成第一次大顶堆
    交换堆顶和数组最后一个元素位置,再从n-1开始重新构建大顶堆
    重复n-1次完成有序序列 

void adjustHeap(int i,int n){
	int temp = a[i];
	for(int k=2*i+1;k<n;k=k*2+1){
		if(k+1<n&&a[k]<a[k+1]){
			k++;
		}
		if(a[k]>temp){
			a[i] = a[k];
			i = k;
		}
		else
			break; 
	}
	a[i] = temp;
}

void heapSort(int n){
	for(int i=n/2-1;i>=0;i--){
		adjustHeap(i,n);
	}
	for(int j = n-1;j>0;j--){
		int t = a[0];
		a[0] = a[j];
		a[j] = t;
		adjustHeap(0,j);
	}
}

7.二路归并排序原理:
    将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
    1. 将无序的原始序列左右分组,直到序列只有2个元素
    2.对其进行比较排序
    3.一层层返回,直到得到有序的序列 

void Merge(int sourcrArr[],int tempArr[],int startIndex,int midIndex,int endIndex)
{
    int i=startIndex,j=midIndex+1,k=startIndex;
    while (i!=midIndex+1&&j!=endIndex+1) {
        if (sourcrArr[i]>sourcrArr[j]) {
            tempArr[k++]=sourcrArr[j++];
        }
        else
            tempArr[k++]=sourcrArr[i++];
    }
    while (i!=midIndex+1) {
        tempArr[k++]=sourcrArr[i++];
    }
    while (j!=endIndex+1) {
        tempArr[k++]=sourcrArr[j++];
    }
    for (i=startIndex; i<=endIndex; i++) {
        sourcrArr[i]=tempArr[i];
    }
}
void MergeSort(int sourcrArr[],int tempArr[],int startIndex,int endIndex)
{
    int midIndex;
    if (startIndex<endIndex) {
        midIndex=(startIndex+endIndex)/2;
        MergeSort(sourcrArr, tempArr, startIndex, midIndex);
        MergeSort(sourcrArr, tempArr, midIndex+1, endIndex);
        Merge(sourcrArr, tempArr, startIndex, midIndex, endIndex);
    }
}

8.    计数原理:
    (适用于小范围集合的排序) 
    1.取另一数组以无序数组的值作为标记,记录出现的次数
    2.对所有的计数累加,即该数组的某一标记记录了小于等于该标记数组值之和;
    3.反向填充新数组,cout[a[i]]-1作为新数组的标记,记录a[i]的值 

void countSort(int a[],int n){
	int i;
	for(i=0;i<n;i++){
		b[a[i]]++;
	}
	for(i=1;i<1000;i++){
		b[i] += b[i-1];
	}
	for(i=n;i>0;i--){
		c[b[a[i-1]]-1] = a[i-1];
		b[a[i-1]]--;
	}
}

9.    基数排序原理:
    它是透过键值的部分信息,将要排序的元素分配至某些“桶”中,藉以达到排序的作用。
    基数排序(以整形为例),将整形10进制按每位拆分,然后从低位到高位依次比较各个位。主要分为两个过程: 
  (1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中; 
  (2)收集,再将放置在0~9号桶中的数据按顺序放到数组中;

int getDigitInPos(int num,int pos){     //用于得到位数 
	int i,temp = 1;
	for(i=0;i<pos-1;i++){
		temp *=10;
	}
	return (num/temp)%10;
}

void radixSort(int n){
	int i,j;
	for(i=0;i<10;i++){
		radix[i][0]=0;
	}
	for(int pos = 1;pos<=10;pos++){
		for(i=0;i<n;i++){
			int num = getDigitInPos(a[i],pos);    //获取每个位数的数字
			int index =  ++radix[num][0];
			radix[num][index] = a[i];
		}
		for(i=0,j=0;i<10;i++){
			for(int k = 1;k<=radix[i][0];k++){
				a[j++] = radix[i][k];
			}
			radix[i][0]=0;
		}
	}
}

10.    桶排序原理:
    桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序
    1.设置一个定量是数组作为空桶
    2.遍历输入数组,以元素作为下标放于对应桶中
    3.对每个不是空的桶进行排序
    4.从不是空的桶里把排序好的数据拿出。 

void bucketSort(int n){
	int max=0,i;
	for(i=0;i<n;i++){
		if(max<a[i]){
			max = a[i];
		}
	}
	for(i=0;i<n;i++){
		arr[a[i]]++;
	}
	for(int j=0,i=0;j<=max;j++){
		while(arr[j]-->0){
			a[i++] = j; 
		}
	}
} 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值