Замена строк в матрице с

Обновлено: 06.07.2024

если вы собираетесь поменять местами строки [0] и строки [1], результирующая матрица будет:

ребята, можете ли вы помочь мне получить код на C для этого?

Ответ полностью зависит от того, как реализована ваша "матрица", потому что язык c не имеет понятия о такой вещи.

Вы используете двумерные массивы?

Или что-то другое?

Двумерные массивы

Вам придется перемещать отдельные элементы вручную.

(Вот r1 а также r2 это целые, которые были установлены на два ряда, которые вы хотите поменять местами) memcpy реализация, которая вполне может быть быстрее, но требует целой строки временного воспоминания.

Рваные Массивы

Если эта операция очень распространена и профилирование показывает, что она отнимает много времени, вы можете рассмотреть вариант использования матрицы с рваным массивом. Что-то вроде этого:

Самое интересное в этой структуре - то, что вы все еще можете получить к ней доступ с помощью [][] запись, но операция обмена строк становится

С вашей точки зрения, у рваных массивов есть два недостатка (ну, в общем, три причины проблем с управлением памятью): они требуют дополнительной памяти для указателей строк, и вы не можете использовать встроенную инициализацию.

Ряд-а-astructure

C не поддерживает присвоения массивов формы;

но он поддерживает семантику присваивания значений для структур. Что дает вам реализацию, которую несколько человек предложили без объяснения:

который гладкий Требуется целый ряд памяти, но если компилятор хорош, то, вероятно, быстро. Большим недостатком является то, что вы не можете обращаться к отдельным элементам матрицы с помощью [][] синтаксис больше. Скорее ты пишешь m[i].r[j] ;

другие

Существует множество способов реализовать "матрицу" в c, но в большинстве случаев они намного сложнее и полезны только в специализированных ситуациях. К тому времени, когда они вам понадобятся, вы сможете сами ответить на эти вопросы в контексте каждого из них.

Решить эту домашнюю работу?

Я бы, вероятно, поменял один элемент за раз, чтобы избежать использования большого количества дополнительного хранилища. Если вы работаете в основном с такими вещами, как графические преобразования, где матрицы обычно имеют размер 3x3 или 4x4, подход Джеймса Керрана, вероятно, будет немного лучше. Если вы (или возможно) работаете с действительно большими матрицами, это сэкономит память и, возможно, будет работать быстрее:

Hy! это мой первый пост о переполнении стека, я знаю, что он довольно длинный, надеюсь, меня не забанят!

Вероятно, одним из наиболее элегантных подходов было бы использование функции, которая меняет местами два полученных аргумента - используя ее для обмена компонентами матрицы. Скажем, что-то вроде своп (а, б). Как уже говорили многие, мы должны рассмотреть возможность использования вспомогательной переменной

Вы можете легко использовать эту операцию, чтобы поменять местами два элемента (a и b) - я считаю, что это не по теме, но я настоял на этой идее, потому что нашел ее довольно интересной. Наконец, отвечая на ваш вопрос, вы можете использовать, скажем,

имея матрицу, объявленную как

Вы можете использовать XOR-способ для замены строк, сначала идентифицируя элементы, которые нужно поменять местами (в соответствии с индексом строки, как вы уже сказали)

Я надеюсь, что это будет полезно в вашей дальнейшей практике.

Также попробуйте этот пример, я уверен, что впоследствии вы поймете всю идею намного лучше (не забудьте, что индекс матрицы начинается с 0!)

Необходимо поменять местами две строки матрицы. Нашел в интернете несколько примеров в которых используется поэлементный обмен. Мне такой код не очень нравится, поэтому я написал свой вариант обмена строк матрицы с использованием ссылочных переменных и указателей, но вот беда - я сам не до конца понимаю как он работает ( он работает, проверял на произвольных матрицах ).

(В данном конкретном случае меняю местами строки в зависимости от четности индекса)

Практическим путем выяснил что " *matrix[i] " возвращает значение первого элемента i-ой строки. Честно говоря, не понятно почему так. Знаю, что имя массива это указатель на его первый элемент, видимо, это как-то связано, но точную логическую цепочку не получается провести.

Ссылочная переменная " temp " получает адрес этого первого элемента i-ой строки.

Как работает " matrix[i+1] = &temp; " не очень понятно.


18.7k 3 3 золотых знака 22 22 серебряных знака 35 35 бронзовых знаков Зачем вы писали это T &temp = *matrix[i]; - совершенно не понятно. Это лишь запутывает код. Можно было просто написать T *temp = matrix[i]; matrix[i] = matrix[i+1]; matrix[i+1] = temp; . А у вас получился просто кусок кода с "четным количеством несуразностей", в результате чего они компенсируют друг друга. Да, я уже после сделал так, как вы написали. Буду использовать именно такую версию, но все равно интересно получить объяснение на то, как работает код с ссылочными переменными. Си изучаю недавно, поэтому некоторые нюансы работы с ссылками\указателями не понятны. @toopeachok, судя по тому, что функция является шаблонной, это C++ , но не C .

Необходимо поменять местами две строки матрицы.

Во-первых, надо определиться, каким образом объявляется матрица.

Самый простой подход - это объявить матрицу в виде двумерного массива. Например,

В этом случае приведенная вами функция не годится, то есть не будет работать, так как она принимает указатель на указатель в качестве аргумента, а не двумерный массив.

Для вашей функции матрица определяется скорей всего динамически (хотя в частном случае это может быть и локальный массив) как указатель на динамически выделенный одномерный массив, элементы которого в свою очередь являются указателями на динамически выделенные одномерные массивы.

Теперь указатель a можно передать в вашу функцию в качестве первого аргумента.

Внутри этой функции обмениваются соседние элементы динамически созданного массива a , которые являются указателями на первые элементы других выделенных динамически массивов, как

Здесь выражение matrix[i] дает значение элемента, то есть значение указателя, в i-ом элементе массива matrix . Этот указатель содержит адрес первого элемента i-го динамически выделенного массива.

объявляет ссылку на этот первый элемент i-го . Поэтому если взять адрес этого первого элемента, используя ссылку

то значение выражения &item будет равно значению, хранящемся в выражении matrix[i] .

Эквивалентный код может выглядеть следующим образом

Имейте в виду, что есть стандартная функция std::swap , объявленная в заголовке <utility> . которая выполняет данную операцию. С помощью этой функции вы могли бы просто написать

Ниже представлена демонстрационная программа, которая использует два подхода к определению матрицы: первый - в виде массива и второй - в виде набора динамических массивов.

Вывод программы на консоль:

44.1k 3 3 золотых знака 36 36 серебряных знаков 86 86 бронзовых знаков

Указатель matrix содержит адрес указателья(является указателем на указатель). matrix[i] это указатель (matrix + i) , *matrix[i] это первый элемент в массиве(строке) matrix + i .

означает, что первому элементу i - той строки придаем имя temp

теперь matrix[i] указывает на начало того же массива, что и matrix[i + 1]

matrix[i+1] = &temp; теперь i + 1 - тый указатель получает значение: адрес первого элемента i - той строки, равно, указывает на строку i

Практически вы могли бы написать функцию проще:


14.2k 3 3 золотых знака 10 10 серебряных знаков 27 27 бронзовых знаков

В представленном коде происходит следующее:

Эта шаблонная функция первым аргументом принимает указатель на указатель на какой-то тип. Судя по всему, предполагается, что этот тип является элементарным. Например, int , float , double .

Исходя из того, что matrix - это указатель на указатель, ваша матрица представлена как массив, в котором хранятся указатели на массивы (строки), в которых хранятся сами элементы:

введите сюда описание изображения

Где matrix - это указатель, в котором хранится адрес массива ABC ;

Происходит обход всей матрицы по строкам. Здесь сразу видны две проблемы:

  1. Нет контроля значения переменной rowsQuantity ;
  2. Переменная типа int не вполне подходит для адресации элементов массива. Переменная типа size_t подойдет гораздо лучше.

Действия выполняются при посещении каждой строки, чей индекс кратен двум (0, 2, 4, и пр.). И действия, соответственно, выполняются попарно над строками 0-1, 2-3, 4-5.Это не совсем рационально, потому что такой подход выполняет в два раза больше инкрементов переменной i , в два раза больше делений с остатком и в два раза больше сравнений, чем реально необходимо.

Гораздо рациональнее было бы выполнять i += 2 , вообще отбросив деление с остатком и проверку. Но такой подход потребует выполнение проверки целочисленного переполнения переменной i .

На первый взгляд, это довольно идиоматическая запись, необходимая для классического обмена местами двух значений с использованием промежуточной переменной:

Но не совсем. Я не уверен до конца, что происходит в недрах компилятора, и что по этому поводу говорит Стандарт .

matrix[i] - получает значение указателя на строку матрицы (адрес массива со значениями строки). * - разыменовывает данный адрес, получая значение (значения) всей строки. По всей видимости, значение строки помещается в ссылочную переменную temp .

Я не специалист по C++ , но мне данный код кажется очень странным. По логике, ссылка является сущностью времени компиляции, иначе говоря - это просто всевдоним для чего-то. То есть, эти три странные строчки можно свести к двум:

В результате чего и в x , и в y будет находится изначальное значение y . Но, по-видимому, компилятор в принципе понимает, что вы от него хотите. А может быть, это неопределенное поведение. Точно сказать не могу, потому что текущий стандарт C++ занимает почти 2000 страниц.

Здесь происходит использование адреса данных, связанных со ссылкой temp .

PS. Я бы рекомендовал как можно реже и меньше смешивать C++ с его C подмножеством. Не потому, что C плохо, а потому что такое смешивание имеет ряд существенных минусов.

Во-первых, низкоуровневая явность C несовместима с высокоуровневой неявностью C++ . Это гарантированно будет приводить к трудным для понимания ошибкам даже во вполне тривиальном коде. Так же это будет вынуждать вас писать еще больше кода, чем при использовании одного только C - вот такой парадокс.

Во-вторых, смешивание ссылок с указателями, шаблонов с макросами и исключений с кодами возврата приводит к неподдающимся анализу ситуациям, потому что названные элементы противоречивы в деталях, хотя поверхностно кажутся очень похожими.

если вы собираетесь поменять местами строку [0] и строку [1], результирующая матрица будет:

вы можете помочь мне получить для этого код на C?

Это домашнее задание? (отметьте, пожалуйста) - Bob

Это домашнее задание? Как определяется ваша матрица? Вы знаете, как поменять местами две переменные типа int? Вы знаете циклы в C? Проявите немного усилий, и оно будет вознаграждено :). - Maciej Hehl

на самом деле это моя домашняя работа. это единственная оставшаяся матричная операция, которую я не знаю, как решить. матрица [100] [100], но строки и столбцы определяются пользователем. на самом деле я уже закончил замену строк, добавление строк, добавление матриц, мульт. так далее. - user420360

спасибо за ссылки mctylr. да, я умею писать для циклов. на самом деле, я пытаюсь понять код обмена строк, а затем просто внести изменения, которые будут соответствовать кодам mt. - user420360

7 ответы

Ответ полностью зависит от того, как реализована ваша «матрица», потому что в языке c такое понятие отсутствует.

Вы используете двумерные массивы?

Или что-то другое?

Двумерные массивы

Придется вручную перемещать отдельные элементы.

(Вот r1 и r2 - это целые числа, которые были установлены в две строки, которые вы хотите поменять местами) или см. Джеймс' memcpy реализация что вполне может быть быстрее, но требует целых рядов временной памяти.

Рваные массивы

Если эта операция очень распространена и профилирование показывает, что она занимает много времени, вы можете подумать об использовании реализации матрицы с рваным массивом. Что-то вроде этого:

Самое интересное в этой структуре то, что вы все еще можете получить к ней доступ с помощью [][] обозначение, но операция перестановки строк становится

Рваные массивы имеют два недостатка с вашей точки зрения (ну, три из-за проблем с управлением памятью): они требуют дополнительного хранилища для указателей строк, и вы не можете использовать встроенную инициализацию.

Ряд как структура

C не поддерживает присвоение формы массивам;

но это делает поддерживать семантику присваивания по значению для структур. Это дает вам реализацию, предложенную несколькими людьми без объяснения причин:

что гладко. Для этого требуется целый ряд памяти, но, если компилятор хорош, скорее всего, он будет быстрым. Большим недостатком является то, что вы не можете адресовать отдельные элементы матрицы с помощью [][] синтаксиса больше. Скорее ты пишешь m[i].r[j] ;

Другое

Есть много, много других способов реализовать «матрицу» в c, но в большинстве случаев они намного сложнее и полезны только в специализированных ситуациях. К тому времени, когда они вам понадобятся, вы сможете ответить на эти вопросы для себя в контексте каждого из них.

ответ дан 23 мая '17, 14:05

еще раз спасибо! Я использую 2-й код. однако, когда я попробовал матрицу 2x3, возникла ошибка. третий столбец или столбец [2] не меняются местами. - user420360

я имею в виду, что элементы строки в последнем столбце не меняются местами - user420360

@user обратите внимание на пределы for петля. Если ваши строки имеют длину 3, цикл должен выполняться от 0 до 2, что обычно строится с помощью for(i=0;i<3;++i) . Новички нередко пишут for(i=0;i<2;++i) который не работает или for(i=0;i<=2;++i) что будет, но выглядит странно (не идиоматично) для программистов на C. - dmckee --- котенок экс-модератора

Я понял это в цикле for. я user420360

ответ дан 23 авг.

Хороший. Самое приятное здесь то, что он работает для Любой реализация с непрерывными строками. - dmckee --- котенок экс-модератора

Хороший ответ, хорошее использование typedef, чтобы сделать код более читабельным. Но я боюсь, что это, скорее всего, не отвечает на OP, так как я подозреваю, что это просто идет ему в голову. - mctylr

Большое спасибо за ответ. Я новичок в C, и мы еще не закончили обсуждение с memcpy - user420360

Я бы, вероятно, поменял местами по одному элементу, чтобы не использовать много дополнительного хранилища. Если вы работаете в основном с такими вещами, как графические преобразования, где матрицы обычно имеют размер 3x3 или 4x4, подход Джеймса Каррана следующий: вероятно Немного лучше. Если вы работаете (или можете работать) с действительно большими матрицами, это сэкономит память и, возможно, будет работать быстрее:

ответ дан 23 авг.

решить это твое домашнее задание?

ответ дан 24 авг.

Вы должны добавить сюда обсуждение; Тем более, что это вопрос новичка. Этот трюк работает из-за семантики присваивания структур. - dmckee --- котенок экс-модератора

Обмен выглядит неплохо. Но это: row[1].m[2] = . отстой. Хм, в том-то и дело, не так ли? - Мацей Хель

Значит, дело было не в этом. Вы действительно хотели, чтобы ответ был полезным, а не просто озорной попыткой наказать ОП? Я бы не догадался. - Мацей Хель

Эй! Это мой первый пост о переполнении стека, я знаю, что он довольно длинный, надеюсь, меня не забанят!

Вероятно, одним из самых элегантных подходов было бы использование функции, которая меняет местами два полученных аргумента, используя ее для обмена компонентами матрицы. Скажем что-нибудь вроде своп (а, б). Как уже многие говорили, мы должны рассмотреть возможность использования вспомогательной переменной

Вы можете легко использовать эту операцию, чтобы поменять местами два элемента (a и b) - я считаю, что это не по теме, но я настоял на этой идее, потому что мне это показалось довольно интересным. Наконец, отвечая на ваш вопрос, вы можете использовать, скажем,

при наличии матрицы, объявленной как

Вы можете использовать свой способ XOR для замены строк, сначала идентифицируя элементы, которые необходимо заменить (в соответствии с индексом строки, как вы уже сказали)

Надеюсь, это будет полезно в вашей дальнейшей практике.

Также попробуйте этот пример, я уверен, что впоследствии вы поймете всю идею намного лучше (не забывайте, что индекс матрицы начинается с 0!)

если вы goint для замены строки [0] и строки [1], итоговой матрицей будет:

Можете ли вы, ребята, помочь мне получить код в C для этого?

Ответ полностью зависит от того, как реализована ваша "матрица", потому что язык c не имеет понятия о такой вещи.

Используете ли вы двухмерные массивы?

Двумерные массивы

Вам придется перемещать отдельные элементы вручную.

(здесь r1 и r2 - это ints, которые были установлены в две строки, которые вы хотите обменять) или см. Джеймс memcpy реализация, которые может быть быстрее, но требует целых строк, имеющих временную память.

Ragged Arrays

Если эта операция очень распространена, и профилирование показывает, что она потребляет много времени, вы можете подумать об использовании реалистичной реализации матрицы. Что-то вроде этого:

Интересная часть этой структуры состоит в том, что вы все еще можете получить к ней доступ с нотой [][] , но операция смены строк будет

Рваные массивы имеют два недостатка с вашей точки зрения (ну, три из-за проблем с управлением памятью): им требуется дополнительное хранилище для указателей строк, и вы не можете использовать встроенную инициализацию.

Ряд-а-astructure

C не поддерживает назначения массива формы;

но он поддерживает семантику присваивания значения для структур. Это дает вам реализацию, которую предложили несколько человек, не объяснив:

который является гладким. Для этого требуется целая строка памяти, но если компилятор хорош, это, вероятно, быстро. Большим недостатком является то, что вы больше не можете обращаться к отдельным матричным элементам с синтаксисом [][] . Скорее вы пишете m[i].r[j] ;

Другие

Существует много и много других способов реализации "матрицы" в c, но они в основном намного сложнее и полезны только в специализированных ситуациях. К тому времени, когда они вам понадобятся, вы сможете ответить на эти вопросы для себя в контексте каждого из них.

решить эту домашнюю работу?

Я бы, вероятно, поменял один элемент за раз, чтобы избежать использования большого количества дополнительного хранилища. Если вы работаете в основном с такими вещами, как графические преобразования, где матрицы обычно имеют 3x3 или 4x4, подход Джеймса Каррана, вероятно, немного лучше. Если вы работаете (или, возможно, работаете) с действительно большими матрицами, это сэкономит память и, скорее всего, будет работать быстрее:

Hy! это мой первый пост при переполнении стека, я знаю это довольно долго, надеюсь, что я не стану запрещенным!

Вероятно, одним из самых элегантных подходов будет использование функции, которая свопирует два полученных аргумента - используя их для замены матричных компонентов. Позвольте сказать somethig как swap (a, b).
Как уже говорили многие, мы должны рассмотреть возможность использования вспомогательной переменной

Вы можете легко использовать эту операцию для замены двух элементов (a и b). Я верю, что это не в тему, но я настаивал на этой идее, потому что нашел ее довольно интересной.
Наконец, отвечая на ваш вопрос, вы можете использовать let say

имея матрицу, объявленную как

Вы можете использовать свой путь XOR для свопинга строк, во-первых, идентифицировать элементы, которые необходимо заменить (согласно индексу строки, как вы уже сказали)

Я надеюсь, что это будет полезно в вашей дальнейшей практике.

Также попробуйте этот пример, я уверен, что вы поймете всю идею намного лучше после этого (не забывайте, что индекс матрицы начинается с 0!)

Читайте также: