1.设一系列正整数存放在一个数组中,试设计算法,将所有奇数存放在数组的前半部分,将所有的偶数放在数组的后半部分。要求尽可能少用临时存储单元并使时间最少。
【解答】
算法的设计
①设计swap函数来实现数组的转化,参数列表接收两个int型指针变量L、R,分别指向数组的首元素和尾元素;int型变量temp作为互换取值时的临时变量;如果L表示的地址比R低,进入外层while循环,反之退出循环;L从前向后遍历,R从后向前遍历,L遇到偶数停止遍历,退出内层while循环,R遇到奇数停止遍历,退出内层while循环;继续将当前的L与R所指的值进行互换。
②定义并初始化int数组arr[],int型size表示数组大小,left,right是初始值分别指向数组首元素和尾元素的int指针,调用swap方法并传入两个指针;用for循环遍历输出转化后的数组。
算法的分析
①上述算法中只有一个临时存储空间,temp,占用4个字节。
②时间复杂度:由于设置两个辅助指针分别用来单向遍历数组,并且当辅助指针指向同一个数组元素时,外层while循环结束,数组转化成功,时间复杂度为O(n),由数组的大小决定。
#include <stdio.h> #include <stdlib.h> void swap(int *L, int *R){ int temp = 0; while(L<R){ while(*L%2==1){ L++; } while(*R%2==0){ R--; } if(L < R){ temp = *L; *L = *R; *R = temp; } } } int main(){ int arr[] = {3,7,4,9,6,8,5,0,10,23}; int size = sizeof(arr)/sizeof(arr[0]); int *left = arr; int *right = arr+size-1; swap(left,right); for(int i=0;i<size;i++){ printf("%d ",arr[i]); } return 0; }
2.设计一个算法,计算一个三元组表示的稀疏矩阵的对角线元素之和。并分析算法的时间复杂度。
【解答】
算法的设计
①设计zip、sum函数分别实现矩阵压缩和对角线元素求和;
②zip函数的设计思路是,将数组中非零元素的值、行下标和列下标分别赋给三元组元素中的data、i和j。传入结构体指针依次为三元组数组元素赋值。返回三元组中数据元素的数量。
③sum函数将成员符合i==j或i+j==列长-1的三元组的data值累加求和。
算法的分析
①上述算法中zip函数使用内外两层for循环遍历矩阵,而sum函数使用一层for循环遍历三元组数组。
②时间复杂度:O(m*n)
#include <stdio.h> #include <stdlib.h> #define MAXSIZE 30 #define m 5 #define n 5 // 定义三元组 typedef struct{ int i; int j; int data; }Triple; // 矩阵压缩 int zip(int arr[m][n], Triple *t){ int index=0; int i,j; for(i=0;i<m;i++) for(j=0;j<n;j++){ if(arr[i][j]!=0){ t->i=i+1,t->j=j+1; t->data=arr[i][j]; t++; index++; } } return index; } // 对角线求和 int sum(Triple t[], int size){ int s=0; for(int k=0;k<size;k++){ if(t[k].i==t[k].j||(t[k].i+t[k].j)==n-1){ s=s+(t[k].data); } } return s; } int main(){ // 定义一个数组 int arr[m][n]={{0,0,6,4,0}, {7,3,8,0,0},{0,0,4,0,2}, {6,3,0,0,0},{4,0,9,0,1} }; // 初始化一个三元组 Triple t[MAXSIZE]={}; Triple *T=t; int size = zip(arr,T); int s=sum(t,size); printf("%d",s); return 0; }