排序算法总结

【C++】排序算法 冒泡排序、插入排序、选择排序、希尔排序、堆排序、归并排序、快速排序、计数排序、基数排序、桶排序、外排序 阅读详情

1 插入排序

(1)直接插入排序

//直接插入排序
void insertSort(int a[], int n) {
    for (int i = 1; i < n; ++i) {
        int temp = a[i];//待插入元素
        int j;
        for (j = i; j >= 1 && temp < a[j-1]; --j) {//0-i-1有序
            a[j] = a[j-1];
        }
        a[j] = temp;

    }
}

基本操作是元素移动次数,时间复杂度O(n2)

(2)折半插入排序

void binInsertSort(int a[], int n) {
    for (int i = 1; i < n; i++) {
        int temp = a[i];
        int l = -1;
        int r = i;
        while (r - l > 1) {//找大于等于temp的最小元素(r)
            int mid = l + (r - l) / 2;
            if (a[mid] >= temp) {
                r = mid;
            }
            else {
                l = mid;
            }
        }
        int j = i - 1;
        for (; j >= r; --j) {//r到i-1的元素整体后移一位
            a[j + 1] = a[j];
        }
        a[j + 1] = temp;
        //a[r]=temp;
    }
}

基本操作次数没有改变,因此时间复杂度依然为O(n2)

(3)希尔排序

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

时间复杂度与增量的选取有关,以上采用的选取方法时间复杂度为O(n2)

交换类排序

(1)冒泡排序

void bubbleSort(int a[], int n) {
    for (int i = 0; i < n - 1; ++i) {
        bool flag = true;
        for (int j = 0; j < n - i - 1; ++j) {
            if (a[j] > a[j + 1]) {
                int temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
                flag = false;
            }
            
        }
        if(flag){//若在一趟冒泡中未交换说明已经有序
            break;
        }
    }
}

时间复杂度O(n2)

(2)快速排序

快速排序1.0
左边都是小于等于,右边都是大于。(默认以第一个元素做划分)

void quickSort(int a[], int low, int high) {
	if (low < high) {
		int temp = a[low];
		int r = low;//先剔除第一个元素,所以初始小于等于的右边界为low
		int i = low + 1;
		while (i <= high) {
			if (a[i] <= temp) {//如果小于等于temp,则与右边界的下一个数作交换,同时右边界右移
				swap(a[i], a[r + 1]);
				++r;
				++i;
			}
			else {
				++i;
			}
		}
		swap(a[r], a[low]);//最后右边界上数与第一个元素交换,这样r左边都是小于等于的,右边都是大于的
		quickSort(a, low, r - 1);
		quickSort(a, r + 1, high);

	}
	
}

快速排序2.0
左边小于,中间等于,右边大于

void quickSort(int a[], int low, int high) {
	if (low < high) {
		int temp = a[low];
		int r = low;//小于的右边界
		int l = high + 1;//大于的左边界
		int i = low + 1;//先剔除第一个元素
		while (i < l) {
			if (a[i] < temp) {//若小于temp,则与右边界的下一个值交换,同时右边界向右扩充
				swap(a[i], a[r + 1]);
				++i;
				++r;
			}
			else if (a[i] > temp) {//若大于temp,则与左边界的下一个值交换,同时左边界向左扩充
				swap(a[i], a[l - 1]);
				--l;
			}
			else {
				++i;
			}
		}
		swap(a[low], a[r]);//最后将右边界上的数与第一个元素交换,同时右边界左移一位
		--r;
		quickSort(a, low, r);//此时r是小于的右边界,l是大于的左边界,(r,l)之间就是相等的元素。
		quickSort(a, l, high);
	}
}

快排3.0
随机选择一个数作划分。

void quickSort(int a[], int low, int high) {
	if (low < high) {
		int n = high - low + 1;
		int index = rand() % n;//随机选择一个位置
		swap(a[low], a[low + index]);//先将划分值交换到第一个位置
		int r = low;
		int l = high + 1;
		int i = low + 1;
		while (i<l) {
			if (a[i] < a[low]) {
				swap(a[i], a[r + 1]);
				++r;
				++i;
			}
			else if (a[i] > a[low]) {
				swap(a[i], a[l - 1]);
				--l;
			}
			else {
				++i;
			}
		}
		swap(a[r], a[low]);
		quickSort(a, low, r - 1);
		quickSort(a, l, high);

	}

}

另一种写法

void quickSort(int a[], int low, int high) {
    if (low < high) {
        int temp = a[low];
        int i = low;
        int j = high;
        while (i < j) {
            while (i < j && a[j] >= temp)--j;
            if (i < j) {
                a[i++] = a[j];
            }
            while (i < j && a[i] < temp)++i;
            if (i < j) {
                a[j--] = a[i];
            }
        }
        a[i] = temp;
        quickSort(a, low, i - 1);
        quickSort(a, i + 1, high);
    }
}

时间复杂度O(NlogN),空间复杂度O(logN)
应用:
找第k大的元素:每一轮快排都选择一个枢轴,使得左边的元素都小于这个枢轴,右边的元素都大于等于这个枢轴。
若枢轴右边的元素(包含枢轴)正好等于k的话,说明枢轴就是第k大的元素;
若枢轴右边的元素(包含枢轴)小于k的话,说明第k大的元素在枢轴左边;
若枢轴右边的元素(包含枢轴)大于k的话,说明第k大的元素在枢轴右边.

int kMostLarge(int a[], int n,int low, int high, int k) {//第k大的元素
    if (low <= high) {
        int temp = a[low];
        int i = low;
        int j = high;
        while (i < j) {
            while (i < j && a[j] >= temp)--j;
            if (i < j) {
                a[i++] = a[j];
            }
            while (i < j && a[i] < temp)++i;
            if (i < j) {
                a[j--] = a[i];
            }
        }
        a[i] = temp;
        if (n - i == k) {//i右边的元素个数(包含i)
            return a[i];
        }
        else if (n - i < k) {
            return kMostLarge(a, n, low, i - 1, k);
        }
        else {
            return kMostLarge(a, n, i + 1, high, k);
        }
    }
    return -1;
}

选择排序

(1)简单选择排序

void selectSort(int a[], int n) {
    for (int i = 0; i < n - 1; ++i) {
        int minPos = i;
        for (int j = i + 1; j < n; ++j) {
            if (a[j] < a[minPos]) {
                minPos = j;
            }
        }
        int temp = a[minPos];
        a[minPos] = a[i];
        a[i] = temp;
    }
}

(2)堆排序

void sift(int a[], int low, int high) {//调整函数
    int i = low;
    int j = 2 * i + 1;
    int temp = a[i];
    while (j <= high) {
        if (j<high && a[j + 1]>a[j])++j;
        if (a[j] > temp) {
            a[i] = a[j];
            i = j;
            j = 2 * j + 1;
        }
        else {
            break;
        }
    }
    a[i] = temp;
}
void heapSort(int a[], int n) {
    for (int i = n / 2 - 1; i >= 0; --i) {//初始堆
        sift(a, i, n-1);
    }
    for (int i = n - 1; i >= 1; --i) {
        int temp = a[i];
        a[i] = a[0];
        a[0] = temp;
        sift(a, 0, i - 1);
    }
}

二路归并排序

void merge(int a[], int low, int mid, int high) {
	int n1 = mid - low + 1;
	int n2 = high - mid;
	int* a1 = new int[n1];
	int* a2 = new int[n2];
	for (int i = 0; i < n1; ++i) {
		a1[i] = a[low + i];
	}
	for (int i = 0; i < n2; ++i) {
		a2[i] = a[mid +1+ i];
	}
	int i = 0;
	int j = 0;
	int k = 0;
	while (i < n1 && j < n2) {
		if (a1[i] <= a2[j]) {
			a[low+k] = a1[i++];
			k++;
		}
		else {
			a[low + k] = a2[j++];
			k++;
		}
	}
	while (i < n1) {
		a[low + k] = a1[i++];
		k++;
	}
	while (j < n2) {
		a[low + k] = a2[j++];
		k++;
	}
}
void mergeSort(int a[], int low, int high) {
    if (low < high) {
        int mid = (low + high) / 2;
        mergeSort(a, low, mid);
        mergeSort(a, mid + 1, high);
        merge(a, low, mid, high);//合并
    }
}

非递归实现

void mergeSort2(int a[], int low, int high) {
	int n = high - low + 1;//数组的长度
	int step = 1;
	while (step < n) {
		int ls = low;//左边的子数组的开始位置
		while (ls < n) {
			int lf = ls + step - 1;//左边的子数组的结束位置
			if (lf >= n) {
				break;
			}
			int rf = min(lf + step, n - 1);//右边子数组的结束位置
			merge(a, ls, lf, rf);
			ls = rf + 1;
			
		}
		if (step > n / 2) {//防止step溢出(超出int最大值)
			break;
		}
		step = step << 1;
	}

}

归并排序的时间复杂度O(N*lonN),空间复杂度O(N),要借助辅助数组存放左右数组
应用:
1.规定一个整型数组,计算每个数左边比它小的数之和,最后返回所有数的这些和之和。
例如(2,4,3,4),2左边没有比他小的,4左边有一个2比他小,3左边有一个2比他小,4左边有2和3比它小。所有最终返回2+2+2+3=9.

分析:转换思路,求每个数左边比它小的数转换为这个数右边有几个数比它大。
采用归并策略:假设当前有左右两个数组,两个指针分别指向这两个数组的起始位置。
如果左边指针所指的元素比右边的小,则在右边数组这个范围内从右边数组指针所指元素开始到右边数组的结束位置都比左边大。然后将左边拷贝到原数组,左指针后移;
如果左边指针所指的元素比右边的大,则右边没有比它大的,右边拷贝到原数组,右指针后移;
如果左边指针所指的元素等于右边的,则右边拷贝到原数组,右指针后移。(因为无法确定比左边大的个数)

int merge(int a[], int low, int mid, int high) {
	if (low <= high) {
		int n1 = mid - low + 1;
		int n2 = high - mid;
		int* a1 = new int[n1];
		int* a2 = new int[n2];
		for (int i = 0; i < n1; ++i) {
			a1[i] = a[low + i];
		}
		for (int i = 0; i < n2; ++i) {
			a2[i] = a[mid + 1 + i];
		}
		int i = 0;
		int j = 0;
		int k = 0;
		int re = 0;
		while (i < n1 && j < n2) {
			if (a1[i] < a2[j]) {
				a[low + k] = a1[i];
				re += (n2 - j) * a1[i];
				k++;
				i++;
			}
			else {
				a[low + k] = a2[j++];
				k++;
			}
		}
		while (i < n1) {
			a[low + k] = a1[i++];
			k++;
		}
		while (j < n2) {
			a[low + k] = a2[j++];
			k++;
		}
		return re;
	}
}

int lessSum(int a[], int low, int high) {//返回low到high范围上左边比它小的数之和
	if (low == high) {
		return 0;
	}
	if (low < high) {
		int mid = (low + high) / 2;
		return lessSum(a, low, mid) +
			lessSum(a, mid + 1, high) +
			merge(a, low, mid, high);
	}
}
  1. 给定一个整型数组a,对于a中的某一个元素num,如果num右边有个数的2倍都比num小,则算一个。求所有数的和之和。
    例如:{1,3,1,4}
    1右边没有
    3右边有1个(1)
    1右边没有
    4右边没有
    分析:假设有两个已排好序的左右数组,两个指针分别指向数组的开始位置
    如果左指针的元素>右指针的元素*2,右指针后移;
    否则当前左指针所指元素的和为右指针开始到当前右指针的元素个数
int merge(int a[], int low, int mid, int high) {
	
		int n1 = mid - low + 1;
		int n2 = high - mid;
		int* a1 = new int[n1];
		int* a2 = new int[n2];
		
		for (int i = 0; i < n1; ++i) {
			a1[i] = a[low + i];
		}
		for (int i = 0; i < n2; ++i) {
			a2[i] = a[mid + 1 + i];
		}
		int i = 0;
		int j = 0;
		int k = 0;
		int re = 0;
		int rWindow = mid + 1;//[mid+1,rWindow)为右数组已判断的范围
		while (i<n1) {
			while (rWindow<=high && a1[i]>a[rWindow] * 2) {
				rWindow++;
			}
			re += (rWindow - mid - 1);
			++i;
		}
		i = 0;
		j = 0;
		while (i < n1 && j < n2) {
			if (a1[i] < a2[j]) {
				a[low + k] = a1[i];
				
				k++;
				i++;
			}
			else {
				a[low + k] = a2[j++];
				k++;
			}
		}
		while (i < n1) {
			a[low + k] = a1[i++];
			k++;
		}
		while (j < n2) {
			a[low + k] = a2[j++];
			k++;
		}
		return re;
	
}

int twoSum(int a[], int low, int high) {
	if (low == high) { return 0; }
	if (low < high) {
		int mid = (low + high) / 2;
		return twoSum(a, low, mid) + twoSum(a, mid + 1, high) + merge(a, low, mid, high);
	}
}
  1. 子数组个数
    分析:本题是求子数组之和落在固定范围内的子数组的个数
    首先准备一个前缀和数组sum,sum[i]表示从0到i位置的元素之和。
    于是可以转化为求以i结尾的子数组且之和落在固定范围内的个数(i从0到n-1)。
    如果sum[i]=Y,即求sum[j]>=Y-upper && sum[j]<=Y-lower的个数。
    因此以i结尾的子数组且之和落在固定范围内的个数转化为sum[j]>=Y-upper && sum[j]<=Y-lower的个数。
#define ll long long
class Solution {
public:
    int merge(vector<ll>&sum,int low,int mid,int high,int lower,int upper){
        int n1=mid-low+1;
        int n2=high-mid;
        int* a1=new int[n1];
        int* a2=new int[n2];
        for(int i=0;i<n1;++i){
            a1[i]=sum[low+i];
        }
        for(int i=0;i<n2;++i){
            a2[i]=sum[mid+1+i];
        }
        //[lWindow,rWindow)
        int lWindow=low;
        int rWindow=low;
        int re=0;
        for(int i=mid+1;i<=high;++i){
            ll min=sum[i]-upper;
            ll max=sum[i]-lower;
            while(rWindow<=mid && sum[rWindow]<=max)++rWindow;
            while(lWindow<=mid && sum[lWindow]<min)++lWindow;
            re+=rWindow-lWindow;
        }
        int i=0;
        int j=0;
        int k=0;
        while(i<n1 && j<n2){
            if(a1[i]<=a2[j]){
                sum[low+k]=a1[i++];
                ++k;
            }else{
                sum[low+k]=a2[j++];
                ++k;
            }
        }
        while(i<n1){
            sum[low+k]=a1[i++];
            ++k;
        }
        while(j<n2){
            sum[low+k]=a2[j++];
            ++k;
        }
        delete []a1;
        delete []a2;
        return re;
    }
    int returnCount(vector<ll>&sum,int low,int high,int lower,int upper){
      if(low==high){
          if(sum[low]>=lower && sum[low]<=upper){
              return 1;
          }else{
              return 0;
          }
      }
      int mid=low+((high-low)>>2);
      int leftPart=returnCount(sum,low,mid,lower,upper);
      int rightPart=returnCount(sum,mid+1,high,lower,upper);
      return leftPart+rightPart+merge(sum,low,mid,high,lower,upper);

    }
    int countRangeSum(vector<int>& nums, int lower, int upper) {
        int n=nums.size();
        int result=0;
        vector<ll>sum(n);
        sum[0]=nums[0];
        for(int i=1;i<n;++i){
            sum[i]=sum[i-1]+nums[i];
        }
        return returnCount(sum,0,n-1,lower,upper);
    }
};

计数排序

计数排序是一个非基于比较的排序算法,元素从未排序状态变为已排序状态的过程,是由额外空间的辅助和元素本身的值决定的。前提是数据范围有限。
流程:1.为每个数据建一个桶,遍历所有的数据,统计所有数据出现的次数。
2. 按桶的大小依次放值
基于比较的排序极限O(nlogn)
不基于比较的排序极限O(n)

void countSort(vector<int>&nums,int range) {//数据范围1-range
	vector<int>bucket (range + 1);
	for (int i = 0; i < nums.size(); ++i) {
		bucket[nums[i]]++;//统计数据出现的个数
	}
	int k = 0;
	for (int i = 1; i <=range; ++i) {
		for (int j = 0; j < bucket[i]; ++j) {
			nums[k++] = i;
		}
	}

}

时间复杂度O(N)

基数排序

基数排序也是不基于比较的排序
流程:假设最大的数有3位,则需要3轮排序。
首先按个位排:
准备10个桶,0-9,个位为0的放0号桶,个位为1的放1号桶……
最后从左往右收集桶中的数(桶中的数按先进先出的顺序收集)
然后再按十位排,重复上述步骤,最后再按百位排。
上面分配-收集的辅助变量可以用队列来完成,但还有一个优化的做法:
举个例子:arr:101,130,234,211,342,240
对上述数按个位排序
首先准备一个count数组,大小为10,下标0位置的值表示个位为0的数有几个,下标1位置表示个位为1的数有几个……
count:
然后再准备一个前缀和数组count’,下标0位置表示个位<=0的数有几个,下标1位置表示个位<=1的数有几个……
在这里插入图片描述

最后从右往左arr数组,首先是240,个位为0,查前缀和数组下标0位置是2,那么240一定在1位置上,同时count’0位置减1;
解释一下为什么240一定在1位置上?
count’[0]=2:表示个位小于等于0的数有2个,即个位小于等于0的数一定分布在下标0-1范围上,而又是从右往左收集的,240是最后一个数,必然是占据1这个位置的,否则范围就不会到1.
由于前缀和数组的特性,所以从右往左收集比较方便,如果硬从左往右,需要知道>=0的数有i个,该数一定占据范围的最小位置即n-i。
在这里插入图片描述
然后是342,个位为2,查前缀和数组下标2是5,说明个位小于等于2的有5个,则个位小于等于2的收集结果分布在0-4范围,又因为342是最后一个数,则342在4号位置,同时count’2位置减1;
在这里插入图片描述
接着是211,最终在3位置
在这里插入图片描述
234在5位置
在这里插入图片描述
130在0位置在这里插入图片描述
101在2位置
在这里插入图片描述
最终收集结果:130,240,101,211,342,234与一般方法得到的结果一致。

int returnDigit(int a[], int n) {//返回数组最大的数有几位
	int max = a[0];
	for (int i = 1; i < n; ++i) {
		if (a[i] > max) {
			max = a[i];
		}	
	}
	int digits = 0;
	while (max != 0) {
		++digits;
		max /= 10;
	}
	return digits;
}
int getDigit(int a, int i) {//返回a中第i位的数,如果a不够i位,默认填0
	while (--i) {
		a /= 10;
	}
	return a % 10;
}
void precess(int a[], int l, int r, int digits) {
	for (int i = 1; i <= digits; ++i) {//一共需要3轮排序,i=1表示按个位,i=2表示按十位……
		vector<int>count(10);
		for (int j = l; j <= r; ++j) {//求count数组
			int k = getDigit(a[j], i);//返回a[j]的第i位
			count[k]++;
		}
		vector<int>count_(10);
		count_[0] = count[0];
		for (int p = 1; p < 10; ++p) {//求前缀和数组
			count_[p] = count_[p - 1] + count[p];
		}
		vector<int>help(r-l + 1);
		for (int q = r; q >= l; --q) {//模拟收集
			int k = getDigit(a[q], i);
			help[count_[k]-1] = a[q];
			count_[k]--;
		}
		int k = 0;
		for (int m = l; m <= r; ++m) {
			a[m] = help[k++];
		}

	}
}
//基数排序
void cardinalitySort(int a[],int n) {
	int digits = returnDigit(a,n);//a中最多有几位
	precess(a, 0, n - 1, digits);
}

时间复杂度O(n*log10 max),其中max为数组中最大数,log10 max表示最大数的位数,因此基数排序的时间复杂度与最大数的位数有关。

排序的稳定性

定义:排序前相同值的次序与排序后的次序是否一致,若一致则具备稳定性。
不具备稳定性的排序:快速排序,希尔排序,简单选择排序,堆排序

排序算法:稳定的排序算法 元素,并围绕主元对列表进行分区,将较小的元素放入低数组中,将所有较大的元素放入高数组中。然后,我们对他们的第十位的值进行排序。因此,我们可以对任意大小的列表进行排序,而无需在冒泡排序中使用任何额外的空间。我们可以说,子问题可以被视为对数组的一部分进行排序,从任何索引 s(start) 开始,到任何索引 e(end) 结束。正如我们上面所讨论的,最大堆是一个完全二叉树,其中每个内部节点中的值都大于或等于该节点的子节点中的值。此外,每次迭代后,已排序子数组的大小都会增加,而未排序子数组的大小会减少。 阅读详情

相关推荐

八种排序算法

偶尔有看到排序算法,想起来大学里老师也有讲授过冒泡排序、快速排序等,不过现在已经没什么概念,一查发现排序算法有八种,有的甚至连名字都没听过,感概平时看的少。既然已经看到了,就干脆了解下基础概念,避免在后续学习途中,出现一看就懵逼的情况。   冒泡排序 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到...

dobat的博客 3348

排序算法及其部分知识点

排序 插入排序(InsertSort) 将一个待排序的记录按其关键字大小插入到前面已排好的子序列中 代码实现 void InsertSort(int A[], int n){ int i, j, temp; for(i=1; i<n; i++){ // 将各元素插入到已排好序的子序列中 if(A[i] < A[i-1]){ // 若A[i]关键字小于其前驱 temp = A[i]; // tem

weixin_42456671的博客 857

排序算法总结及C++实现

文章目录1 引入 认识时间复杂度2 补充 对数器3 排序算法分析3.1 基于比较的排序3.1.1 冒泡排序3.1.2 选择排序3.1.3 插入排序3.1.4 归并排序补充题目 小和问题补充题目 逆序数3.1.5 快速排序3.1.6 堆排序3.2 非基于比较的排序3.2.1 计数排序3.2.2 桶排序3.2.3 基数排序4 排序总结4.1 稳定性4.2 工程中的综合排序算法4.3 有关排序...

李滚滚的博客 2222

C语言的插入排序

#include #include #define N 8 void insert_sort(int a[],int n); //插入排序实现,这里按从小到大排序 void insert_sort(int a[],int n)//n为数组a的元素个数 {     //进行N-1轮插入过程     for(int i=1; i     {         //首先找到元素a[i]

开始淡漠的博客 425

排序算法 - 面试中的排序算法总结

排序算法总结 查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。所以在面试中经常会问到排序算法及其相关的问题。但万变不离其宗,只要熟悉了思想,灵活运用也不是难事。 一般在面试中最常考的是快速排序和归并排序,并且经常有面试官要求现场写出这两种排序的代码。对这两种排序的代码一定要信手拈来才行。还有插入排序、冒泡排序、堆排序、基数排序、桶排序等。面试官对

从零开始 2982

【Python&RS】Rasterio库安装+基础函数使用教程

Rasterio是一个Python库,专门用于栅格数据的读写操作。它支持多种栅格数据格式,如GeoTIFF、ENVI和HDF5,为处理和分析栅格数据提供了强大的工具。RasterIO适用于各种栅格数据应用,如卫星遥感、地图制作等。这篇文章跟大家介绍一下Rasterio库的安装以及一些基本函数的使用教程,附带源码。

Remote Sensing迷途小书童 1万+

开开心心学算法:排序算法

排序算法插入排序非递归方法递归方法采用二分法的插入排序归并排序 插入排序 插入排序的操作与起牌的方式类似,从桌上放置的一堆牌中抽取出一张牌,与手中已有序的牌进行比较,将其插入到合适的位置,然后再从桌面上抽取下一张牌,如此反复直到桌面上的牌被抓完。 而 插入排序的原理也是这样的,将一个序列分成左右两部分,左边代表有序的牌,右边代表桌面上待抽取的牌。初始时,我们将序列的第一个元素作为已经抓在手里的第...

sunny_yeah_的博客 384

基于QGIS的DEM地形数据精细化处理:从裁剪、合并到成果输出

本文详细介绍了使用QGIS进行DEM地形数据的精细化处理流程,包括数据获取、裁剪、合并及成果输出等关键步骤。通过实战技巧和注意事项,帮助用户高效处理地形数据,适用于GIS分析、三维建模等应用场景。

weixin_29093017的博客 450

插入排序

题目描述: 设计函数 void InsertSort(int a[],int n); 该函数使用插入排序算法,将数组a的前n个元素按照升序的方式排序。 插入排序算法描述如下: 初始序列:49 38 65 97 76 13 27 49 将元素(38) 插入合适位置: [38 49] 65 97 76 13 27 49 将元素(65) 插入合适位置: [38 49 65] 97 76 13 27 49 将元素(97) 插入合适位置: [38 49 65 97] 76 13 27 49 将元素(76) 插入合适位

m0_49371394的博客 1646

实战指南:基于华为Ascend NPU的大模型W8A8量化调优与精度提升

本文提供了一份基于华为Ascend NPU进行大模型W8A8量化的实战调优指南。详细介绍了从环境搭建、使用msmodelslim框架进行基础量化,到通过离群值抑制、校准集优化和量化回退等关键技术提升精度的全流程。旨在帮助开发者在华为NPU硬件上实现模型推理的显著加速,同时有效控制精度损失。

weixin_29227425的博客 271

Homebrew 必备软件清单:我的 macOS 开发环境搭建全记录

本文详细介绍了如何使用Homebrew在macOS上搭建高效的开发环境,包括基础配置、核心开发工具链、高效编码工具集等30个必备工具。通过Homebrew这一macOS缺失的包管理器,开发者可以一键安装命令行工具和GUI应用,大幅提升工作效率。文章还提供了日常维护命令和疑难问题解决方案,适合从新手到资深开发者的所有用户。

weixin_28836507的博客 353

c语言编程实现简单的插入排序,简单了解C语言中直接插入排序与直接选择排序实现...

直接插入排序基本思路:1. 从a[0]开始,也就是从1个元素开始是有序的,a[1]~a[n-1]是无序的。2. 从a[1]开始并入前面有序的数组,直到n-1。#include #define N 5void insertsort(int a[], int n);void swap(int *x, int *y);void insertsort(int a[], int n){int i,j;for...

weixin_42512613的博客 354

使用html和JavaScript实现一个简易的物业管理系统

码实现了一个简易的物业管理系统,主要使用了以下技术和功能: 1.主要技术 使用的技术: HTML: 用于构建网页的基本结构。 包括表单、表格、按钮等元素。 CSS: 用于美化网页的外观和布局。 设置字体、颜色、边距、对齐方式等样式。 JavaScript: 用于处理用户交互和动态更新页面内容。 实现了新增住户、查询住户、编辑住户、删除住户等功能。 处理表单提交事件,验证输入数据,并更新表格显示。 DOM操作: 使用 JavaScript 直接操作 HTML DOM 元素。 动态

weixin_41312759的博客 1777

九大排序算法再总结

如果要转载,需要注明出处: http://blog.youkuaiyun.com/xiazdong 本文是 http://blog.youkuaiyun.com/xiazdong/article/details/7304239 的补充,当年看了《大话数据结构》总结的,但是现在看了《算法导论》,发现以前对排序的理解还不深入,所以打算对各个排序的思想再整理一遍。 本文首先介绍了基于比较模型的排序算法,

xiazdong 31万+

计算机组成原理实验二 运算器组成实验

事实上,ALU的设计是在全加器的基础上,对全加器功能的扩展来实现符合要求的多种算术/逻辑运算的功能。为了实现多种功能的运算,An、Bn数据是不能直接与全加器相连接的,它们受到功能变量F3—F1的制约,因此,可由An、Bn数据和功能变量F3-F1组合成新的函数Xn 、Yn,然后,再将Xn 、Yn和下一位进位Cn-1通过全加器进行全加运算以实现所需的运算功能。AC寄存器可用来存储ALU的输入以实现两个操作数的运算操作,也可以用来存储来自ALU的结果,以将这些结果反馈给ALU以进行更多的处理。

qq_63574533的博客 1449

Zephyr RTOS详解

Zephyr 是一个开源的实时操作系统(RTOS),专为资源受限的嵌入式设备设计,支持多种架构(如 ARM Cortex-M、RISC-V、x86 等)。

weixin_43484713的博客 4103

「排序算法」十大经典排序算法

文章目录十大经典排序算法一、冒泡排序二、选择排序三、插入排序四、希尔排序五、归并排序六、快速排序七、堆排序八、计数排序九、桶排序十、基数排序 引用网站:菜鸟教程十大经典排序 十大经典排序算法 排序算法图片总结(图片来源于网络) 一、冒泡排序 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢

秋天,黄叶坠地,凉风有信。 6427

扫地机器人行业 企业篇-产业总部地理分布

中国扫地机器人产业呈现区域集聚特征,广东省以13家企业领跑全国,其中深圳独占9家(如大疆、云鲸智能等),佛山、广州、东莞各有分布。江苏省6家企业主要集中在苏州(科沃斯、追觅科技等)。北京聚集了石头科技、小米等4家品牌。浙江、山东、湖南等地也有代表性企业分布。国际品牌方面,美国iRobot、韩国三星/LG、日本松下等均在各自国家设立总部,而戴森、飞利浦等欧洲品牌则将中国运营中心设在上海或苏州。值得注意的是,部分品牌如由利、宝家丽虽为外资起源,但主要运营实体已落户中国。

智能硬件研发,欢迎交流 362

【排序算法】排序算法总结

排序算法总结,将排序算法的分类、稳定性和特点进行一个总结,并附有跳转到对应详解的链接,方便大家学习

weixin_52811588的博客 982

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

稳定排序算法有哪些

稳定排序算法有哪些 相信您已经掌握了很多种排序算法,比如冒泡排序、插入排序、希尔排序、选择排序等。这些排序算法中,有些是 “稳定” 的,有些是 “不稳定” 的。 给定的待排序序列中,经常会包含相同的元素,例如: 3 1 2 4 2 此序列中包含两个元素 2,为了区分它们,我们分别称它们为 “红 2” 和 “绿 2”。 评价一个排序算法是否稳定,是指该算法完成排序的同时,是否会改变序列中相同元素的相对位置。例如,上面序列中红 2 和绿 2 的相对位置是:红 2 位于绿 2 的左侧,或者说绿 2 位于红 2

ccc369639963的博客 1万+

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

十大经典排序算法

十种常见的排序算法可分为以下两大类: 比较类排序:通过比较来决定元素间的相对位置,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。 非比较类排序:不通过比较来决定元素间的相对位置,它可以突破基于比较排序的时间下限,以线性时间运行,因此也称为线性时间非比较类排序。 时间复杂度: 从序列的初始状态到经过排序算法的变换移位等操作变到最终排序好的结果状态的过程所花费的时间度量。

qq_40896594的博客 3672

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

什么是排序算法?常见的排序算法有哪些?

计数排序适用于数据范围较小且已知的情况,其时间复杂度为线性时间,非常适合处理小范围内的数据排序。基数排序适用于整数排序,特别是当数据范围较大但数据量适中时。它通过多次应用计数排序来实现多轮排序,从而克服了传统排序算法在处理大范围数据时的效率问题。

破损的天堂鸟博客 1226

十大排序算法

算法稳定性:单次比较后,两个值相等的邻近元素的位置在排序后,相对位置没有改变。

一名想做出点成就的后端~ 1428

排序算法详解

排序算法是计算机科学中最基础也最重要的算法之一。它将一组数据(例如数字列表、字符串集合)按照特定的顺序(升序或降序)重新排列。高效的排序算法对于优化其他算法(如搜索和合并算法)的效率至关重要。

m0_54069809的博客 1168
上一篇: 图的基本算法
下一篇: 二叉树的递归套路
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值