语言 所有内部排序算法 冒泡法,选择法,插入法,快排法,希尔,归并,堆排序,基数排序
C语言七大算法

C语言七大算法一、概述算法是计算机程序设计中解决问题的方法和步骤的描述,是计算机科学的重要基础。
在计算机科学中,有许多经典的算法被广泛应用,并成为不可或缺的工具。
本文将介绍C语言中的七大经典算法,包括排序算法、查找算法、图算法、字符串算法、动态规划算法、贪心算法和分治算法。
二、排序算法排序是将一组元素按照特定规则进行重新排列的过程。
常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。
这些排序算法在C语言中都有相应的实现,并且各有特点和适用场景。
三、查找算法查找算法用于在一组数据中查找特定值的位置或判断是否存在。
常见的查找算法有线性查找、二分查找、哈希查找等。
这些算法在C语言中的实现可以帮助我们快速地定位目标值。
四、图算法图算法用于解决与图相关的问题,包括最短路径问题、最小生成树问题、拓扑排序等。
在C语言中,我们可以利用图的邻接矩阵或邻接表来实现相关的图算法。
五、字符串算法字符串算法主要用于解决字符串匹配、替换、拼接等问题。
在C语言中,我们可以使用字符串库函数来完成一些基本的字符串操作,例如字符串比较、复制、连接等。
六、动态规划算法动态规划算法是解决一类最优化问题的常用方法,它将问题分解为多个子问题,并通过保存已解决子问题的结果来避免重复计算。
在C语言中,我们可以使用动态规划算法来解决背包问题、最长公共子序列问题等。
七、贪心算法贪心算法是一种通过每一步的局部最优选择来达到全局最优的方法。
贪心算法通常在解决最优化问题时使用,它快速、简单,并且可以给出近似最优解。
C语言中可以使用贪心算法来解决霍夫曼编码、最小生成树等问题。
八、分治算法分治算法是一种将问题分解为多个相同或类似的子问题然后递归解决的方法。
常见的分治算法有快速排序、归并排序等。
在C语言中,我们可以使用分治算法来提高程序的效率和性能。
总结:本文介绍了C语言中的七大经典算法,包括排序算法、查找算法、图算法、字符串算法、动态规划算法、贪心算法和分治算法。
深入浅出-C语言8种经典排序算法

for(i=0;i<n-j;i++) /* 值比较大的元素沉下去后,只把剩下的元素中的最大值再 沉下去就可以啦 */
{ if(a[i]>a[i+1]) /* 把值比较大的元素沉到底 */ { k=a[i]; a[i]=a[i+1]; a[i+1]=k; }
(8)堆排序 我们知道堆的结构是节点 i 的孩子为 2*i 和 2*i+1 节点,大顶堆要求父节点大于等于其 2 个 子节点,小顶堆要求父节点小于等于其 2 个子节点。在一个长为 n 的序列,堆排序的过程是 从第 n/2 开始和其子节点共 3 个值选择最大(大顶堆)或者最小(小顶堆),这 3 个元素之间的选 择当然不会破坏稳定性。但当为 n/2-1, n/2-2, ...1 这些个父节点选择元素时,就会破坏稳定性。 有可能第 n/2 个父节点交换把后面一个元素交换过去了,而第 n/2-1 个父节点把后面一个相 同的元素没有交换,那么这 2 个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳 定的排序算法.
input[j + 1] = input[j]; /* 一边找一边移动元素 */ input[j] = temp; } } }
5.折半插入排序
5
折半插入排序算法是一种稳定的排序算法,比直接插入算法明显减少了关键字之间比较的次
程思想,值得学习
void sort(int num[], int low, int high) {
int i;
while(low<high) {
for(i=low; i<high; i++) /* bubble to high */ if(num[i]>num[i+1]) swap(num[i], num[i+1]);
使用C语言实现12种排序方法

使⽤C语⾔实现12种排序⽅法⽬录1.冒泡排序2.插⼊排序3.折半插⼊排序4.希尔排序5.选择排序6.鸡尾酒排序7.堆排序8.快速排序9.归并排序10.计数排序11.桶排序12.基数排序1.冒泡排序思路:⽐较相邻的两个数字,如果前⼀个数字⼤,那么就交换两个数字,直到有序。
时间复杂度O(n^2),稳定性:这是⼀种稳定的算法。
代码实现:void bubble_sort(int arr[],size_t len){size_t i,j;for(i=0;i<len;i++){bool hasSwap = false; //优化,判断数组是否已经有序,如果有序可以提前退出循环for(j=1;j<len-i;j++){ //这⾥j<len-i是因为最后⾯的肯定都是最⼤的,不需要多进⾏⽐较if(arr[j-1]>arr[j]){ //如果前⼀个⽐后⼀个⼤swap(&arr[j-1],&arr[j]); //交换两个数据hasSwap = true;}}if(!hasSwap){break;}}}2.插⼊排序思路:把⼀个数字插⼊⼀个有序的序列中,使之仍然保持有序,如对于需要我们进⾏排序的数组,我们可以使它的前i个数字有序,然后再插⼊i+1个数字,插⼊到合适的位置使之仍然保持有序,直到所有的数字有序。
时间复杂度:O(n^2) 稳定性:稳定的算法代码实现:void insert_sort(int arr[],int len){int i,j;for(i=1;i<len;i++){int key = arr[i]; //记录当前需要插⼊的数据for(j= i-1;i>=0&&arr[j]>key;j--){ //找到插⼊的位置arr[j+1] = arr[j]; //把需要插⼊的元素后⾯的元素往后移}arr[j+1] = key; //插⼊该元素}}3.折半插⼊排序思路:本质上是插⼊排序,但是通过半分查找法找到插⼊的位置,让效率稍微快⼀点。
十大排序算法总结

十大排序算法总结在计算机科学领域,排序算法是一个非常重要的研究方向。
排序算法可以帮助我们更快速、更有效率地处理大量数据。
在本文中,我们将介绍十大常见的排序算法,包括冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序。
1. 冒泡排序冒泡排序是一种基本的排序算法。
它重复地遍历待排序的序列,一次比较两个元素,如果它们的顺序错误就交换位置,直到整个序列有序为止。
冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1)。
2. 选择排序选择排序是一种简单直观的排序算法。
它的工作原理是:首先在未排序的序列中找到最小元素,然后将其放到序列的起始位置;接着从剩余未排序的元素中继续寻找最小的元素,然后放到已排序序列的末尾。
选择排序的时间复杂度为O(n^2),空间复杂度为O(1)。
3. 插入排序插入排序是一种基本的排序算法。
它的工作原理是:将一个元素插入到已经排好序的序列中,使得插入后的序列仍然有序。
插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。
4. 希尔排序希尔排序是一种改进版的插入排序。
它通过比较距离较远的元素,可以快速地将大元素向右移动,从而减少后续排序的比较次数。
希尔排序的时间复杂度为O(nlogn),空间复杂度为O(1)。
5. 归并排序归并排序是一种分治算法。
它将待排序的序列分成若干个子序列,每个子序列都是有序的。
然后再将有序的子序列合并成最终的有序序列。
归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。
6. 快速排序快速排序是一种基于分治思想的排序算法。
它通过不断地将序列分成两个部分,将较小的元素移动到左边、较大的元素移动到右边,最终将整个序列排好序。
快速排序的时间复杂度为O(nlogn),空间复杂度为O(nlogn)。
7. 堆排序堆排序是一种基于堆的排序算法。
它将待排序的序列看成一棵完全二叉树,每个节点的值都不大于其父节点的值。
然后将最大值不断地从堆中取出,放到已排序序列的末尾。
链表排序(冒泡、选择、插入、快排、归并、希尔、堆排序)

链表排序(冒泡、选择、插⼊、快排、归并、希尔、堆排序)这篇⽂章分析⼀下链表的各种排序⽅法。
以下排序算法的正确性都可以在LeetCode的这⼀题检测。
本⽂⽤到的链表结构如下(排序算法都是传⼊链表头指针作为参数,返回排序后的头指针)struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {}};插⼊排序(算法中是直接交换节点,时间复杂度O(n^2),空间复杂度O(1))class Solution {public:ListNode *insertionSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.if(head == NULL || head->next == NULL)return head;ListNode *p = head->next, *pstart = new ListNode(0), *pend = head;pstart->next = head; //为了操作⽅便,添加⼀个头结点while(p != NULL){ListNode *tmp = pstart->next, *pre = pstart;while(tmp != p && p->val >= tmp->val) //找到插⼊位置{tmp = tmp->next; pre = pre->next;}if(tmp == p)pend = p;else{pend->next = p->next;p->next = tmp;pre->next = p;}p = pend->next;}head = pstart->next;delete pstart;return head;}};选择排序(算法中只是交换节点的val值,时间复杂度O(n^2),空间复杂度O(1))class Solution {public:ListNode *selectSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//选择排序if(head == NULL || head->next == NULL)return head;ListNode *pstart = new ListNode(0);pstart->next = head; //为了操作⽅便,添加⼀个头结点ListNode*sortedTail = pstart;//指向已排好序的部分的尾部while(sortedTail->next != NULL){ListNode*minNode = sortedTail->next, *p = sortedTail->next->next;//寻找未排序部分的最⼩节点while(p != NULL){if(p->val < minNode->val)minNode = p;p = p->next;}swap(minNode->val, sortedTail->next->val);sortedTail = sortedTail->next;}head = pstart->next;delete pstart;return head;}};快速排序1(算法只交换节点的val值,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))这⾥的partition我们参考(选取第⼀个元素作为枢纽元的版本,因为链表选择最后⼀元素需要遍历⼀遍),具体可以参考这⾥我们还需要注意的⼀点是数组的partition两个参数分别代表数组的起始位置,两边都是闭区间,这样在排序的主函数中:void quicksort(vector<int>&arr, int low, int high){if(low < high){int middle = mypartition(arr, low, high);quicksort(arr, low, middle-1);quicksort(arr, middle+1, high);}}对左边⼦数组排序时,⼦数组右边界是middle-1,如果链表也按这种两边都是闭区间的话,找到分割后枢纽元middle,找到middle-1还得再次遍历数组,因此链表的partition采⽤前闭后开的区间(这样排序主函数也需要前闭后开区间),这样就可以避免上述问题class Solution {public:ListNode *quickSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//链表快速排序if(head == NULL || head->next == NULL)return head;qsortList(head, NULL);return head;}void qsortList(ListNode*head, ListNode*tail){//链表范围是[low, high)if(head != tail && head->next != tail){ListNode* mid = partitionList(head, tail);qsortList(head, mid);qsortList(mid->next, tail);}}ListNode* partitionList(ListNode*low, ListNode*high){//链表范围是[low, high)int key = low->val;ListNode* loc = low;for(ListNode*i = low->next; i != high; i = i->next)if(i->val < key){loc = loc->next;swap(i->val, loc->val);}swap(loc->val, low->val);return loc;}};快速排序2(算法交换链表节点,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))这⾥的partition,我们选取第⼀个节点作为枢纽元,然后把⼩于枢纽的节点放到⼀个链中,把不⼩于枢纽的及节点放到另⼀个链中,最后把两条链以及枢纽连接成⼀条链。
793的六种算法

793的六种算法一、插入排序算法插入排序算法是一种简单直观的排序算法,它的基本思想是将待排序的元素插入到已排序序列的适当位置,使得插入后的序列仍然有序。
具体步骤如下:1. 将数组分为已排序区间和未排序区间,初始时已排序区间只有一个元素,即数组的第一个元素。
2. 从未排序区间取出第一个元素,将其与已排序区间中的元素依次比较,找到合适的位置插入。
3. 重复上述步骤,直到未排序区间为空。
插入排序算法的时间复杂度为O(n^2),空间复杂度为O(1),适用于数据量较小的排序场景。
二、冒泡排序算法冒泡排序算法是一种简单的排序算法,它的基本思想是通过相邻元素的比较和交换,将最大或最小的元素逐渐“冒泡”到数组的一端。
具体步骤如下:1. 从数组的第一个元素开始,依次比较相邻的两个元素,如果它们的顺序不对,则交换位置。
2. 重复上述步骤,直到数组中的所有元素都排好序。
冒泡排序算法的时间复杂度为O(n^2),空间复杂度为O(1),适用于数据量较小且基本有序的排序场景。
三、选择排序算法选择排序算法是一种简单直观的排序算法,它的基本思想是每次从未排序的部分选择最小或最大的元素,放到已排序部分的末尾。
具体步骤如下:1. 将数组分为已排序区间和未排序区间,初始时已排序区间为空。
2. 从未排序区间中找到最小或最大的元素,将其放到已排序区间的末尾。
3. 重复上述步骤,直到未排序区间为空。
选择排序算法的时间复杂度为O(n^2),空间复杂度为O(1),适用于数据量较小的排序场景。
四、快速排序算法快速排序算法是一种高效的排序算法,它的基本思想是通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有元素都比另一部分的所有元素小,然后再按此方法对两部分分别进行排序,最终得到有序序列。
具体步骤如下:1. 选择一个基准元素,将数组分成两部分,所有小于基准元素的元素放在左边,所有大于基准元素的元素放在右边。
2. 对左右两部分分别进行快速排序。
10种排序法(冒泡、选择、插入、希尔、归并、快速、堆、拓扑、重点

各种排序算法总结排序算法有很多,所以在特定情景中使用哪一种算法很重要。
为了选择合适的算法,可以按照建议的顺序考虑以下标准:(1)执行时间(2)存储空间(3)编程工作对于数据量较小的情形,(1)(2)差别不大,主要考虑(3);而对于数据量大的,(1)为首要。
主要排序法有:一、冒泡(Bubble)排序——相邻交换二、选择排序——每次最小/大排在相应的位置三、插入排序——将下一个插入已排好的序列中四、壳(Shell)排序——缩小增量五、归并排序六、快速排序七、堆排序八、拓扑排序九、锦标赛排序十、基数排序一、冒泡(Bubble)排序----------------------------------Code 从小到大排序n个数------------------------------------ void BubbleSortArray({for(int i=1;i{for(int j=0;i{if(a[j]>a[j+1]//比较交换相邻元素{int temp;temp=a[i]; a[j]=a[j+1]; a[j+1]=temp;}}}}-------------------------------------------------Code------------------------------------------------ 效率 O(n²),适用于排序小列表。
二、选择排序----------------------------------Code 从小到大排序n个数-------------------------------- void SelectSortArray({int min_index;for(int i=0;i{min_index=i;for(int j=i+1;j 每次扫描选择最小项if(arr[j]if(min_index!=i//找到最小项交换,即将这一项移到列表中的正确位置{int temp;temp=arr[i]; arr[i]=arr[min_index]; arr[min_index]=temp;}}}-------------------------------------------------Code------------------------------------------------------效率O(n²),适用于排序小的列表。
数据结构与算法(12):排序

int[] data = new int[] {10,30,20,60,40,50};
mergesort(data);
for(int i:data) {
System.out.println(i);
}
}
public static void mergesort(int[] arr){
sort(arr, 0, arr.length-1);
例例如,假设有这样一一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步⻓长 为5开始进行行行排序,我们可以通过将这列列表放在有5列列的表中来更更好地描述算法,这样他们就应该 看起来是这样:
13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10
坏的情况下,移动次数为n(n − 1)/2
冒泡排序的时间复杂度为O(n2)。冒泡排序不不需要辅助存储单元,其空间复杂度为O(1)。如果关
键字相等,则冒泡排序不不交换数据元素,他是一一种稳定的排序方方法。
时间复杂度:最好O(n);最坏O(n2);平均O(n2) 空间复杂度:O(1)
稳定性:稳定
二二、选择排序(Selection Sort)
排好序时,元素的移动次数为0。当每一一趟都需要移动数据元素时,总的移动次数为n − 1
选择排序的时间复杂度为O(n2)。选择排序不不需要辅助的存储单元,其空间复杂度为O(1)。选择
排序在排序过程中需要在不不相邻的数据元素之间进行行行交换,它是一一种不不稳定的排序方方法。
时间复杂度:O(n2) 空间复杂度:O(1)
地方方增量量和差值都是delta temp = arr[j-delta]; arr[j-delta] = arr[j]; arr[j] = temp;
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1冒泡法:#include<stdio.h>#include<stdlib.h>void mao_pao(int *a,int n){int i,j,temp,flag;for(i=0;i<n-1&&flag;++i){flag=0;for(j=0;j<n-1;++j){if(a[j]>a[j+1]){flag=1;temp=a[j];a[j]=a[j+1];a[j+1]=temp;}}}}void main(){int *a,i,n;a=(int *)malloc(100);if(NULL==a){printf("allocation failture\n");exit(1);}printf("请输入你要排序的元素的个数\n"); scanf("%d",&n);printf("现在开始输入%d个元素\n",n);for(i=0;i!=n;++i)scanf("%d",&a[i]);mao_pao(a,n);printf("排序后为:\n");for(i=0;i!=n;++i)printf("%d ",a[i]);printf("\n");free(a);}2,选择排序法#include<stdio.h>#include<stdlib.h>void xuan_zhe(int *a,int n) {int i,j,temp,max;for(i=0;i<n-1;++i){max=i;for(j=i+1;j<n;++j){if(a[j]<a[max])max=j;}if(i!=max){temp=a[i];a[i]=a[max];a[max]=temp;}}}void main(){int *a,i,n;a=(int *)malloc(100);if(NULL==a){printf("allocation failture\n");exit(1);}printf("请输入你要排序的元素的个数\n"); scanf("%d",&n);printf("现在开始输入%d个元素\n",n);for(i=0;i!=n;++i)scanf("%d",&a[i]);xuan_zhe(a,n);printf("排序后为:\n");for(i=0;i!=n;++i)printf("%d ",a[i]);printf("\n");free(a);}3,插入排序#include<stdio.h>#include<stdlib.h>void cha_ru(int *a,int n) {int i,j,temp;for(i=0;i<n-1;++i){temp=a[i+1];for(j=i;j>=0&&temp<a[j];--j) a[j+1]=a[j];a[++j]=temp;}}void main(){int *a,i,n;a=(int *)malloc(100);if(NULL==a){printf("allocation failture\n");exit(1);}printf("请输入你要排序的元素的个数\n"); scanf("%d",&n);printf("现在开始输入%d个元素\n",n);for(i=0;i!=n;++i)scanf("%d",&a[i]);cha_ru(a,n);printf("排序后为:\n");for(i=0;i!=n;++i)printf("%d ",a[i]);printf("\n");free(a);}4..快速排序#include<stdio.h>#include<stdlib.h>void kuai_pai(int *a,int low,int high) {int left,right,middle,i,j,temp;left=low;right=high;middle=(left+right)/2;while(left<right){while(left<high&&a[left]<a[middle])left++;while(right>low&&a[right]>a[middle])right--;if(left<=right){temp=a[left];a[left]=a[right];a[right]=temp;left++;right--;}}if(left<high)kuai_pai(a,left,high);if(right>low)kuai_pai(a,low,right);}void main(){int *a,i,n;a=(int *)malloc(100);if(NULL==a){printf("allocation failture\n");exit(1);}printf("请输入你要排序的元素的个数\n"); scanf("%d",&n);printf("现在开始输入%d个元素\n",n);for(i=0;i!=n;++i)scanf("%d",&a[i]);kuai_pai(a,0,n-1);printf("排序后为:\n");for(i=0;i!=n;++i)printf("%d ",a[i]);printf("\n");free(a);}5..shell排序#include<stdio.h>#include<stdlib.h>void shell(int *a,int n){int gap,i,j,temp;for(gap=n/2;gap>0;gap=gap/2)for(i=gap;i<n;i++)for(j=i-gap;j>=0&&a[j]>a[j+gap];j=j-gap) {temp=a[j];a[j]=a[j+gap];a[j+gap]=temp;}}void main(){int *a,i,n;a=(int *)malloc(100);if(NULL==a){printf("allocation failture\n");exit(1);}printf("请输入你要排序的元素的个数\n"); scanf("%d",&n);printf("现在开始输入%d个元素\n",n);for(i=0;i!=n;++i)scanf("%d",&a[i]);shell(a,n);printf("排序后为:\n");for(i=0;i!=n;++i)printf("%d ",a[i]);printf("\n");free(a);}6.二路归并排序#include<stdio.h>#include<stdlib.h>void gui_bin(int *a,int *b,int k,int n) {int l1,l2,i,j,u1,u2,l=0;l1=0;while(l1+k<n){l2=l1+k;u1=l2-1;u2=(l2+k-1<n)?l2+k-1:n-1;i=l1;j=l2;while(i<=u1&&j<=u2){if(a[i]<=a[j])b[l++]=a[i++];elseb[l++]=a[j++];}while(i<=u1)b[l++]=a[i++];while(j<=u2)b[l++]=a[j++];l1=u2+1;}for(i=l1;i<n;++i)b[l++]=a[i];}void main(){int *a,*b,i,n,k=1;a=(int *)malloc(100);if(NULL==a){printf("allocation failture\n");exit(1);}b=(int *)malloc(100);if(NULL==b){printf("allocation failture\n");exit(1);}printf("请输入你要排序的元素的个数\n"); scanf("%d",&n);printf("现在开始输入%d个元素\n",n);for(i=0;i!=n;++i)scanf("%d",&a[i]);while(k<n){gui_bin(a,b,k,n);for(i=0;i<n;++i)a[i]=b[i];}printf("排序后为:\n");for(i=0;i!=n;++i)printf("%d ",a[i]);printf("\n");free(a);free(b);}7.堆排序思想是,跟节点都比他们的儿子节点都大,之后从第一个非叶子节点开始到最上的跟节点,依次求其的跟节点,最上的根节点就是值最大的点,这样取得最大值之后,继续求根节点,就能得到一个有序序列。
这里要数以的是因为所有节点都在数组里保存,又因为数组的下标是从0开始的,因此跟节点i对应的叶子节点就是,2*I+1和2*I+2,而第一个非叶子节点是(n-2)/2.#include<stdio.h>#include<stdlib.h>void dui_paixue(int *a,int n,int m){int i,j,l,temp;j=2*i+1;temp=a[i];while(j<n){if(j<n-1&&a[j]<a[j+1])j++;if(a[j]<temp)break;else{a[i]=a[j];i=j;j=2*i+1;}}a[i]=temp;}void dui(int *a,int n){int i;for(i=(n-2)/2;i>=0;i--){dui_paixue(a, n, i);}}void main(){int *a,*b,i,j,temp,n,k=1;a=(int *)malloc(100);if(NULL==a){printf("allocation failture\n"); exit(1);}b=(int *)malloc(100);if(NULL==b){printf("allocation failture\n");exit(1);}printf("请输入你要排序的元素的个数\n");scanf("%d",&n);printf("现在开始输入%d个元素\n",n);for(i=0;i!=n;++i)scanf("%d",&a[i]);dui(a,n);for(j=n-1;j>=0;--j){temp=a[0];a[0]=a[j];a[j]=temp;dui_paixue( a, j, 0);}printf("排序后为:\n");for(i=0;i!=n;++i)printf("%d ",a[i]);printf("\n");free(a);free(b);}8.基数排序(我写的这个基数排序可能效率有点低,也肯能有点小BUG,等着以后改进吧)#include<stdio.h>#include<stdlib.h>#define max 10void main(){int p[10][10];int a[max],i,j,m,n,k,count,flag=1,temp;for(i=0;i!=10;++i){for(j=0;j!=10;++j)p[i][j]=-999;}printf("请输入你要输入的元素的个数\n"); scanf("%d",&n);printf("请输入%d个元素\n",n);for(i=0;i!=n;++i)scanf("%d",&a[i]);for(i=0;i!=n;++i){count=0;k=a[i];while(k>0){m=k%10;k=k/10;count++;}while(p[count][m]!=-999){if(p[count][m]>a[i]){temp=p[count][m];p[count][m]=a[i];a[i]=temp;}elsem++;}p[count][m]=a[i];}for(i=0;i!=10;i++)for(j=0;j!=10;j++){if(p[i][j]!=-999)printf("%d ",p[i][j]); }}。