, например, с учетом матрицы:
1 2 3
4 5 6
7 8 9
если вы собираетесь поменять местами строку [0] и строку [1], результирующая матрица будет:
4 5 6
1 2 3
7 8 9
Можете ли вы, ребята, помочь мне получить код на C для этого?
Ответ полностью зависит от того, как реализована ваша "матрица", потому что в языке c нет такого понятия.
Вы используете двумерные массивы?
double m[3][3];
Или что-то еще?
Вам придется перемещать отдельные элементы вручную.
for (i=0; i<ROWLENGTH; ++i){
double temp;
temp = m[r2][i];
m[r2][i] = m[r1][i];
m[r1][i] = temp;
}
(здесь r1
и r2
— это целые числа, которые были установлены для двух строк, которые вы хотите поменять местами) или см. реализацию Джеймса memcpy
что может быть быстрее, но требует целых строк временной памяти.
Если эта операция очень распространена и профилирование показывает, что она занимает много времени, вы можете рассмотреть возможность использования реализации матрицы неоднородного массива. Что-то вроде этого:
double **m;
m = malloc(sizeof(double*)*NUMROWS);
/* put error checking here */
for (i=0; i<NUMROWS; ++i){
m[i] = malloc(sizeof(double)*ROWLENGTH);
/* error checking again */
}
Самое интересное в этой структуре то, что вы по-прежнему можете обращаться к ней с помощью [][]
нотации, но операция замены строк становится
double *temp;
temp = m[r2];
m[r2] = m[r1];
m[r1] = temp;
Рваными массивами, с вашей точки зрения, есть два недостатка (ну, три из-за проблем с управлением памятью): им требуется дополнительное хранилище для указателей строк, и вы не можете использовать встроенную инициализацию.
C не поддерживает присваивание массива формы;
double r[3], q[3] = { 1, 2, 3 };
r = q; /* ERROR */
но поддерживает семантику присваивания по значению для структур. Что дает вам реализацию, предложенную несколькими людьми без объяснения причин:
typedef struct { double r[ROWLENGTH] } row;
row m[NUMROWS] = { {1, 2, 3}, {4, 5, 6}, {7, 8 9}};
row temp = m[2];
m[2] = m[1];
m[1] = temp;
что очень удобно.Для этого требуется целая строка памяти, но если компилятор хорош, он, вероятно, быстр. Большим недостатком является то, что вы больше не можете обращаться к отдельным матричным элементам с синтаксисом [][]
. Скорее вы пишете m[i].r[j]
;
Есть много, много других способов реализовать "матрицу" в c, но они в основном намного сложнее и полезно только в особых случаях. К тому времени, когда они вам понадобятся, вы сможете ответить на эти вопросы для себя в контексте каждого из них.
typedef int Row[3];
Row Matrix[3];
Row Temp;
memcpy(Temp, Matrix[0], sizeof(Row));
memcpy(Matrix[0], Matrix[1], sizeof(Row));
memcpy(Matrix[1], Temp, sizeof(Row));
решить эту проблему твое домашнее задание?
typedef struct {int m[3];} Row;
typedef int RowAccess[3];
main()
{
Row tmp,row[]={{1,2,3},{4,5,6},{7,8,9}};
RowAccess *rowa=row;
tmp=row[0];
row[0]=row[1];
row[1]=tmp;
/* easy access to matrix here: (is this what you want?) */
rowa[0][0]=0;
rowa[0][1]=1;
...
return 0;
}
Я бы, вероятно, менял по одному элементу за раз, чтобы избежать использования большого количества дополнительной памяти. Если вы работаете в основном с такими вещами, как графические преобразования, где матрицы обычно 3x3 или 4x4, подход Джеймса Куррана вероятно немного лучше. Если вы работаете (или можете работать) с действительно большими матрицами, это сэкономит память и, вполне возможно, будет работать быстрее:
int x[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
for (int i=0; i<3; i++) {
int temp = x[0][i];
x[0][i] = x[1][i];
x[1][i] = temp;
}
Эй! это мой первый пост о переполнении стека, я знаю, что он довольно длинный, надеюсь, меня не забанят!
Возможно, одним из самых элегантных подходов было бы использование функции, которая меняет местами два полученных аргумента — использование ее для замены компонентов матрицы. Скажем что-то вроде swap(a,b). Как многие уже говорили, нам следует подумать об использовании вспомогательной переменной
auxiliary = a ;
a = b ;
b = auxiliary ;
Недавно я подобрался к новому методу, который показался мне впечатляющим, с использованием побитовой операции XOR (http://en.wikipedia.org/wiki/ Xor), поэтому вспомогательная функция не нужна
a ^= b ;
b ^= a ;
a ^= b ;
Вы можете легко использовать эту операцию, чтобы поменять местами два элемента ( a и b ) - я думаю, что это не по теме, но я настаивал на этой идее, потому что нашел ее довольно интересной. Наконец, отвечая на ваш вопрос, вы можете использовать, скажем,
int swap (int *a , int *b){
(*a)^=(*b);
(*b)^=(*a);
(*a)^=(*b);
return 0;
}
, имея матрицу, объявленную как
#define ROW_COUNT 5
#define COLUMN_COUNT 5
....
int a[ROW_COUNT][COLUMN_COUNT];
. Вы можете использовать свой способ XOR для замены строк, во-первых, определяя элементы, которые необходимо поменять местами (в соответствии с индексом строки, как вы уже сказали )
printf("\nSwap Row: "); scanf("%d", &swp1) ; // first row index
printf("With Row: "); scanf("%d", &swp2); // second row index
for (j = 0 ; j < COLUMN_COUNT ; j++){
swap( &a[swp1][j] , &a[swp2][j] );
}
Надеюсь, это пригодится вам в дальнейшей практике.
Также попробуйте этот пример, я уверен, что впоследствии вы поймете всю идею намного лучше (не забывайте, что индекс матрицы начинается с 0 !)
#include "stdio.h"
#include "conio.h"
#define ROW_COUNT 5
#define COLUMN_COUNT 5
int swap (int *a , int *b){
(*a)^=(*b);
(*b)^=(*a);
(*a)^=(*b);
return 0;
}
int main(){
int i, j ;
int swp1, swp2 ;
int a[ROW_COUNT][COLUMN_COUNT];
// Create ( ROW_COUNT X COLUMN_COUNT ) random matrix
for (i = 0 ; i < ROW_COUNT ; i++ )
for (j = 0 ; j < COLUMN_COUNT ; j++ ) a[i][j] = rand();
// Display matrix before row swap
for (i = 0 ; i < ROW_COUNT ; i++ ){
for (j = 0 ; j < COLUMN_COUNT ; j++ ) printf("%d\t",a[i][j]);
printf("\n");
}
// Elements to be swapped
printf("\nSwap Row: "); scanf("%d", &swp1) ; // first row index
printf("With Row: "); scanf("%d", &swp2); // second row index
// Swapping right here
for (j = 0 ; j < COLUMN_COUNT ; j++){
swap( &a[swp1][j] , &a[swp2][j] );
}
// Display once again
printf("\n");
for (i = 0 ; i < ROW_COUNT ; i++ ){
for (j = 0 ; j < COLUMN_COUNT ; j++ ) printf("%d\t",a[i][j]);
printf("\n");
}
getch();
return 0;
}