- 算法思想:采用一维数组arr[]存放人的编号,先将n个人的编号存入到arr[0]~arr[n-1]中。从编号为1的人(下标=0)开始循环报数,数到m的人arr[t](下标=(t+m-1)%i,i表示当前未出列的人数)输出并将其从数组中删除(即将后面的元素前移一个位置),因此每次报数的起始位置就是上次报数的出列位置。反复执行直到出列n个人为止。
void josephus(int n, int m)
{
int i, j, arr[MaxSize];
for (i = 0; i < n; i++) arr[i] = i + 1;
int t = 0;
for (i = n; i > 0; i--)
{
t = (t + m - 1) % i;
printf("%d ", arr[t]);
for (j = t + 1; j < n; j++) arr[j-1] = arr[j];
}
}
- 算法思想:采用类似于十字链表的思路,将每个集合元素设计成带头结点的单链表,将这些集合元素头结点串起来构成一个单链表,设置h所指的结点作为集合头结点。
数据结点的类型声明:
typedef struct dnode
{
int data;
struct dnode *next;
}DType;
集合元素头结点的类型声明:
typedef struct hnode
{
DType *next;
struct hnode *link;
}HType;
(1)生成以下两个稀疏矩阵的三元组a和b
[ 1 0 3 0 0 1 0 0 0 0 1 0 0 0 1 1 ] \begin{bmatrix} 1 & 0 & 3 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 1 & 1\\ \end{bmatrix} ⎣⎢⎢⎡1000010030110001⎦⎥⎥⎤
[ 3 0 0 0 0 4 0 0 0 0 1 0 0 0 0 2 ] \begin{bmatrix} 3 & 0 & 0 & 0\\ 0 & 4 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 2\\ \end{bmatrix} ⎣⎢⎢⎡3000040000100002⎦⎥⎥⎤
void DispMat(TSMatrix t)
{
if (t.nums <= 0) return;
printf("\t%d\t%d\t%d\n", t.rows, t.cols, t.nums);
printf("\t------------------\n");
for (int i = 0; i < t.nums; i++)
printf("\t%d\t%d\t%d\n", t.data[i].r, t.data[i].c, t.data[i].d);
}
void CreateMat(TSMatrix &t,ElemType A[M][N])
{
t.cols = M;
t.rows = N;
t.nums = 0;
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
{
if (A[i][j] != 0)
{
t.data[t.nums].d = A[i][j];
t.data[t.nums].r = i;
t.data[t.nums].c = j;
t.nums++;
}
}
}
(2)输出a转置矩阵的三元组
void TranTat(TSMatrix t, TSMatrix& ta)
{
int k1=0;
if (t.nums <= 0) return;
ta.cols = t.cols;
ta.rows = t.rows;
ta.nums = t.nums;
for(int v=0;v<t.cols;v++)
for (int k = 0; k < t.nums; k++)
{
if (t.data[k].c == v)
{
ta.data[k1].r = t.data[k].c;
ta.data[k1].c = t.data[k].r;
ta.data[k1].d = t.data[k].d;
k1++;
}
}
}
(3)输出a+b的三元组
bool SumMat(TSMatrix a, TSMatrix b, TSMatrix &c)
{
int i = 0, j = 0, k = 0;
ElemType v;
if (a.rows != b.rows || a.cols != b.cols) return false; //行数或列数不等时不能进行相加运算
c.cols = a.cols; c.rows = a.rows; //c的行列数与a的相同
while (i < a.nums && j < b.nums) //处理a和b中的每一个元素
{
if (a.data[i].r == b.data[j].r) //行号相等时
{
if (a.data[i].c < b.data[j].c) //a元素的列号小于b元素的列号
{
c.data[k].r = a.data[i].r; //将a元素添加到c中
c.data[k].c = a.data[i].c;
c.data[k].d = a.data[i].d;
k++; i++;
}
else if (a.data[i].c > b.data[j].c) //a元素的列号大于b元素的列号
{
c.data[k].r = b.data[j].r; //将b元素添加到c中
c.data[k].c = b.data[j].c;
c.data[k].d = b.data[j].d;
k++; j++;
}
else //a元素的列号等于b元素的列号
{
v = a.data[i].d + b.data[j].d;
if (v != 0) //只将不为0的结果添加到c中
{
c.data[k].r = a.data[i].r;
c.data[k].c = a.data[i].c;
c.data[k].d = v;
k++;
}
i++; j++;
}
}
else if (a.data[i].r < b.data[j].r) //a元素的行号小于b元素的行号
{
c.data[k].r = a.data[i].r; //将a元素添加到c中
c.data[k].c = a.data[i].c;
c.data[k].d = a.data[i].d;
k++; i++;
}
else //a元素的行号大于b元素的行号
{
c.data[k].r = b.data[j].r; //将b元素添加到c中
c.data[k].c = b.data[j].c;
c.data[k].d = b.data[j].d;
k++; j++;
}
c.nums = k;
}
return true;
}
- 算法思想:fun(int a[][],int n):用二维数组a存放m阶螺旋方阵。m阶螺旋方阵共有[n/2]圈,对于第i(0≤i≤m-1共执行m次)圈循环,产生该圈上横行的数字,产生该圈右竖行的数字,产生该圈下横行的数字,产生该圈左竖行的数字。最后输出该方阵。
#include
#define MaxSize 10
typedef int ElemType;
void fun(ElemType arr[MaxSize][MaxSize], int n)
{
int i, j, k = 0, m;
if (n % 2 == 0) m = n / 2;
else m = n / 2 + 1;
for (i = 0; i < m; i++)
{
for (j = i; j < n - i; j++)
{
k++;
arr[i][j] = k;
}
for (j = i + 1; j < n - i; j++)
{
k++;
arr[j][n - i - 1] = k;
}
for (j = n - i - 2; j >= i; j--)
{
k++;
arr[n - i - 1][j] = k;
}
for (j = n - i - 2; j >= i + 1; j--)
{
k++;
arr[j][i] = k;
}
}
}
int main()
{
ElemType a[MaxSize][MaxSize];
int n;
printf("输入n(n<10):");
scanf("%d", &n);
fun(a, n);
printf("输出%d阶螺旋方阵:\n", n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf("% 4d ", a[i][j]);
printf("\n");
}
return 0;
}
- 算法思想:MinMax(int A[][]):先求出每行的最小值元素,放人min[m]中,再求出每列的最大值元素,放入max[n]中,若某元素既在min[i]中,又在max[j]中,则该元素A[i][j]便是马鞍点。
#include
#define M 4
#define N 4
typedef int ElemType;
void MinMax(int A[M][N])
{
bool have = false;
ElemType min[M], max[N];
for (int i = 0; i < M; i++)
{
min[i] = A[i][0];
for (int j = 1; j < N; j++)
if (A[i][j] < min[i]) min[i] = A[i][j];
}
for (int j = 0; j < N; j++)
{
max[j] = A[0][j];
for (int i = 1; i < M; i++)
if (A[i][j] > max[j]) max[j] = A[i][j];
}
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
if(min[i]==max[j])
{
printf("A[%d][%d]=%d\n", i, j, A[i][j]);
have = true;
}
if (have == false) printf("没有马鞍点!\n");
}
int main()
{
ElemType A[M][N] = { {9,7,6,8},{20,26,22,25},{28,36,25,30},{12,4,2,6} };
printf("A矩阵:\n");
for (int i = 0; i < M; i++)
{
for (int j = 0; j < M; j++)
printf("% 4d", A[i][j]);
printf("\n");
}
printf("A矩阵中的马鞍点:\n");
MinMax(A);
return 0;
}
- 算法思想:建立一个m行n列的二维数组b,b[i,j]为a中左上角为a[0,0]、右下角为a[i,j]的子矩阵的所有元素之和。
void sum(ElemType a[][MaxSize], ElemType b[][MaxSize], int m, int n)
{
int i, j;
b[0][0] = a[0][0];
for (i = 1; i < m; i++) b[i][0] = b[i - 1][0] + a[i][0]; //求b的第0列
for (j = 1; j < n; j++) b[0][j] = b[0][j-1] + a[0][j]; //求b的第0行
for (i = 1; i < m; i++) //求b[i][j]
for (j = 1; j < n; j++)
b[i][j] = a[i][j] + b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
}
ElemType submat(ElemType b[][MaxSize], int i, int j, int s, int t)
{
if (s == 0 && j == 0) return b[s][t];
return b[s][t] - b[s][j - 1] - b[i - 1][t] + b[i - 1][j - 1];
}
- 算法思想:i从n-1到0循环,累计a[0…i-1]中大于a[i]的元素个数c,置a[i]为c。本算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
void fun(ElemType arr[MaxSize], int n)
{
int i, j, count;
for (i = n - 1; i >= 0; i--)
{
count = 0;
for (j = 0; j < i; j++)
if (arr[j] < arr[i]) count++;
arr[i] = count;
}
}
(2)设有一个元素递增的整型数组a,且所有元素均不相同。使a[i]的值变为a[0]到a[i-1]中小于原a[i]值的个数。
- 算法思想:由于数组a中元素递增且所有元素均不相同,置a[0]=0,用i从0到n-1循环。temp保存[i-1]元素值,若a[i]>temp,置a[i]=a[i-1]+1,否则a[i]=a[i-1]。本算法的时间复杂度为O(n)。
void fun(ElemType arr[MaxSize], int n)
{
int i, j, temp = arr[0];
arr[0] = 0;
for (i = 1; i < n; i++)
{
if (arr[i] > temp) arr[i] = arr[i - 1] + 1;
else arr[i] = arr[i - 1];
}
}
- 算法思想:设含有n个整数的序列a[0…n-1]的任何连续子序列a[i…j](i≤j,0≤i≤n-1,i≤j≤m-1),求出它的所有元素之和thisSum,并通过比较将最大值存放在maxSum中,最后返回maxSum。
long maxSubSum1(int a[], int n)
{
int i, j, k, thisSum, maxSum = a[0];
for (i = 0; i < n; i++) //两重循环穷举所有的连续子序列
for (j = i; j < n; j++)
{
thisSum = 0;
for (k = i; k <= j; k++)
{
thisSum = thisSum + a[k];
if (thisSum > maxSum) maxSum = thisSum; //通过比较求最大连续子序列之和
}
}
return maxSum;
}
void fun(ElemType a[n], ElemType b[][n])
{
int i, j, k, m = 0, g, gs;
for (k = 1; k <= 2 * n - 1; k++) //对于每条对角线循环一次
{
if (k < n) gs = k; //gs为第k条斜线上的元素个数
else gs = 2 * n - k;
for (g = 1; g <= gs; g++)
{
if (k % 2 == 1) //k为奇数的情况,从下向上递增
{
i = gs - g;
j = g-1;
}
else //k为偶数的情况,从上向下递增
{
i = g-1;
j = gs - g;
}
if (k > n) //考虑第n+1到2n-1的斜线
{
i = i + n - gs;
j = j + n - gs;
}
b[i][j] = a[m++];
}
}
}