Архив метки: программирование

Что означает += в Java?

В Java есть несколько операторов, которые можно использовать для присвоения значений переменным, известных как операторы присваивания. Среди них наиболее часто используемые операторы присваивания — «=» , «+=» , «-=» и т. д. В этой статье мы рассмотрим различные аспекты оператора «+=» , который называется «оператор присваивания сложения» . Оператор «+=» позволяет нам выполнять сложение и присваивание за один шаг.

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

    • Что означает += в Java
    • Поведение оператора += по отношению к типам данных

  • Как использовать += для увеличения значения
  • Как использовать += в циклах
  • Как использовать += для конкатенации строк

Итак, приступим!

 

Что означает += в Java

Это сокращенный оператор присваивания, обычно называемый «оператором присваивания составного сложения». Оператор += выполняет две функции за один раз, т. е. сначала выполняет сложение операндов, а затем присваивает результат левому операнду.

Проще говоря, мы можем сказать, что переменная1 += переменная2 имеет тот же смысл, что и переменная1 = переменная1 + переменная2.

 

Поведение оператора += по отношению к типам данных

Поведение оператора += зависит от типа данных операндов, т.е. если операнды являются строками, то он используется для конкатенации, а если операнды являются числами, то он используется для чисел.

 

Как использовать += для увеличения значения

В java оператор ++ увеличивает значение на 1, однако, используя оператор присваивания сложения, мы можем указать приращение по нашему выбору.

Пример

Предположим, у нас есть переменная «number», которая содержит значение 50, теперь, если нам нужно увеличить ее на 5, мы можем сделать это следующим образом:

publicclassAssignmentOperatorExample {

publicstaticvoidmain(String[] args) {

        int number = 50;

        number +=5;

System.out.println(number);

  }

 }

}

 

Приведенный выше вывода мы видим, что число увеличивается на 5.

 

Как использовать += в циклах

Оператор присваивания сложения может использоваться в структурах циклов Java для увеличения значения более чем на единицу.

 

Пример

Если нам нужно напечатать таблицу «5», мы можем использовать цикл for и внутри цикла мы можем увеличивать значение в пять раз на каждой итерации:

publicclassAssignmentOperatorExample {

publicstaticvoidmain(String[] args) {

for(inti=5; i<=50; i+=5 )

        {

System.out.println(i);

        }

    }

}

 

В приведенном выше фрагменте кода мы инициализируем цикл с «5» и указываем критерии завершения как «i<=50» . Затем мы используем оператор «+=» , который будет увеличивать значение на 5 на каждой итерации. Таким образом, будет выполнено 10 итераций, пока значение «i» не удовлетворит условию завершения, т. е . «i <= 50».

Приведенный выше фрагмент кода проверяет работу оператора +=.

 

Как использовать += для конкатенации строк

Оператор += может использоваться для конкатенации строк:

 

Пример

Давайте рассмотрим приведенный ниже фрагмент кода для глубокого понимания того, как объединить строки с помощью оператора += в java:

publicclassAssignmentOperatorExample {

publicstaticvoidmain(String[] args) {

        String str = "Andrey";

        str += "Ex";

System.out.println(str);

}

}

 

Исходная строка — «Andrey», и мы объединяем с ней «Ex» с помощью оператора +=.

 

Вывод

В Java оператор += используется для выполнения двух функций за один раз, т.е. сначала он выполняет сложение, а затем присваивание. Используя оператор +=, можно выполнить сложение или конкатенацию в зависимости от типа данных операндов. Более того, оператор += можно использовать в качестве оператора приращения в циклах Java.

В этой статье представлен всесторонний обзор оператора += , где мы узнали о различных вариантах использования оператора java +=.



2022-04-08T08:55:05
Java

Что такое метод и как вызвать метод в Java?

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

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

  1. Что такое Java-метод
  2. Синтаксис метода
  3. Как создать метод
  4. Как вызвать метод

 

Итак, начнем!

 

Что такое метод в Java

Метод, также известный как функция, представляет собой блок кода/инструкции, который может принимать или не принимать входные данные в качестве параметров/аргументов и возвращает некоторый результат. Указанный блок кода будет выполняться только тогда, когда кто-то вызывает/вызывает его. В java метод должен быть создан/объявлен внутри класса.

 

Синтаксис метода Java

Ниже будет синтаксис объявления метода:

public static void firstFunction(){

statement(s);

}

 

Здесь, в приведенном выше фрагменте кода, public — это модификатор/описатель доступа, static — ключевое слово, void — тип возвращаемого значения, а firstFunction() — имя определяемого пользователем метода.

Java предлагает несколько модификаторов доступа, таких как default, private, public и protected. Эти модификаторы определяют тип доступа к функции, как указано ниже:

  • Модификатор доступа public определяет, что функция доступна для всех классов/подклассов.
  • Модификатор доступа protected указывает, что метод доступен только внутри определенного пакета.
  • Модификатор доступа private определяет, что функция доступна только тем классам, где она указана
  • Модификатор доступа default определяет, что функция доступна для классов того же пакета.

Java имеет широкий спектр ключевых слов, которые имеют некоторые специальные значения и используются для определенных целей, например, ключевое слово static определяет, что функция может получить доступ к статическим данным.

Тип возвращаемого значения определяет тип данных, которые будут возвращены функцией; например, void используется, когда тип данных не возвращается.

 

Как создать метод в Java

В Java метод можно создать, указав его имя, и мы должны следовать соглашению об именах в верблюжьем регистре.

Для более глубокого понимания давайте рассмотрим пример, который позволит вам понять, как создать пользовательский метод Java:

 

Пример

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

public class MethodExample{

  static void findCube(){

  int number, cube;

  Scanner scan = new Scanner(System.in);

  System.out.print("Enter a Number: ");

  number = scan.nextInt();

  cube = number * number * number;

  System.out.println("Cube of  " + number + "  is :  " + cube);

 }

 

У нас есть класс «MethodExample», и внутри класса мы создали метод findCube(). Затем мы использовали встроенный класс Scanner, чтобы получить данные, вводимые пользователем. После этого у нас есть переменная «cube», в которой будет храниться куб числа.

 

Как вызвать метод в Java

Как только создание метода завершено, мы можем вызвать его, указав имя метода, за которым следует (), как мы сделали в следующем фрагменте кода:

public static void main(String[] args) {

 findCube();

}

 

Для лучшего понимания рассмотрим полный фрагмент кода и его вывод:

Что такое метод и как вызвать метод в Java?

 

Использование класса сканера помогает нам получать ввод от пользователя, и когда мы запускаем код, пользователь вводит число «3», и, следовательно, мы получаем куб этого числа, т.е. «27». Он показывает уместность пользовательского метода.

 

Заключение

Метод, также известный как функция, представляет собой блок кода/инструкции, который может принимать или не принимать входные данные в качестве параметров/аргументов и возвращает некоторый результат. Более того, указанный блок кода будет выполняться только тогда, когда кто-то вызывает/вызывает его. В java метод можно создать, указав модификатор доступа, тип возвращаемого значения, за которым следует определяемое пользователем имя метода. И чтобы вызвать метод, нам нужно указать имя метода, за которым следуют маленькие скобки (). В этой статье представлен подробный обзор того, что такое метод и как вызывать метод в Java, а для более глубокого понимания в нем приводится пример вместе с описательным снимком экрана.



2022-04-04T18:18:18
Java

Метод Mutator в Java

В английском словаре Mutator означает иметь новую форму. Итак, Mutator, хотя и не найден в английском словаре, означает нечто, вызывающее изменение в новую форму. Частная переменная — это поле или свойство класса в Java. В Java нет предопределенного метода, называемого Mutator. Вместо этого Mutator — это метод в классе, и этот метод предназначен для изменения значения частной переменной класса. По соглашению программист должен начинать имя метода с «set». Таким образом, метод может быть чем-то вроде setAge(), setPrice(), setName() и т. д.

 

Разница между частной и общедоступной переменной

Закрытая переменная видна только членам (свойствам и методам) внутри определения класса. Его нельзя увидеть кодом вне определения класса. С другой стороны, общедоступная переменная может быть видна кодом вне определения класса. Код вне класса может просто изменить общедоступную переменную класса, присвоив новое значение, используя имя класса, если метод является статическим, или используя имя объекта, если метод не является статическим. С общедоступной переменной смысла мутации на самом деле нет. Но когда класс изменяет свое собственное значение, которое не может быть изменено извне, это называется трансформацией, в которой лучше понимается мутация.

 

Иллюстрация Mutator

Не каждому классу нужен Mutator. Однако, когда Mutator необходим для частной переменной (свойства), метод Mutatorа, который является членом класса, должен начинаться с «set». Затем программист определяет метод Mutatorа.

Любой объект в магазине может быть определен классом. Например, хорошая чашка в магазине может быть определена классом. Как минимум, класс будет иметь свойство, которое является ценой чашки, метод Mutatorа и метод доступа. Метод доступа — это метод чтения значения свойства. По соглашению метод доступа должен начинаться с «get». В данном случае это будет getPrice(). Пусть свойство с названием price будет частным. Если цена является общедоступной, то нет необходимости в Mutatorе и аксессоре, так как значение может быть установлено или получено (прочитано) публично.

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

    class Cup {

        private double price = 2.0;

        private Character currency = '$';

        public void setPrice(Double dbl) {

            price = dbl;

        }

        public double getPrice() {

            return price;

        }

    }

 

Mutator setPrice() является общедоступным, поэтому к нему можно получить доступ из кода вне класса. Сделать Mutator общедоступным не означает сделать общедоступным соответствующее свойство. Соответствующее свойство должно быть частным. У Mutatorа здесь есть аргумент dbl, который является новой ценой. При изменении рыночных условий меняется и цена в магазине. Если бы цена была общедоступной, не было бы необходимости в Mutatorе setPrice(), поскольку код вне класса мог бы изменить цену. Поскольку setPrice является членом класса, он может видеть значение цены частного свойства. Однако код вне класса не может видеть это свойство. Это по дизайну.

Аксессор getPrice() является общедоступным, поэтому к нему можно получить доступ из кода вне класса. У него нет аргументов. Если бы цена была общедоступной, не было бы необходимости в методе доступа getPrice(), поскольку код вне класса мог бы прочитать цену. Поскольку getPrice является членом класса, он может видеть значение цены частной собственности. Однако код вне класса не может видеть это свойство. Это по дизайну.

Mutator setCurrency() и метод доступа getCurrency() могут быть аналогичным образом написаны для закрытой переменной currency.

Следующий основной класс и основной метод получают доступ к частной переменной price, изменяют переменную, а затем снова обращаются к переменной; все это после создания экземпляра класса:

    public class TheClass {

        public static void main(String[] args) {

            Cup cup1 = new Cup();

            double firstPrice = cup1.getPrice();

            System.out.print(firstPrice); System.out.print(", ");



            cup1.setPrice(3.0);



            double secondPrice = cup1.getPrice();

            System.out.print(secondPrice);

            System.out.println();

        }

    }

 

Результат:

   2.0, 3.0

 

Первый сегмент кода в основном методе создает экземпляр объекта Cup (cup1) и получает доступ к цене частного свойства через методы доступа getPrice() и cup1. Затем он распечатывает эту первую цену с запятой и пробелом.

Второй сегмент кода представляет собой сегмент кода из одной строки. Он изменяет цену частной собственности с помощью Mutatorа setPrice() и cup1. Третий сегмент кода считывает и печатает новую цену.

 

Проверка

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

            boolean bl = dbl instanceof Double;

 

Оператор instance of возвращает true, если его левый операнд является экземпляром правого операнда; ложно в противном случае.

При проверке определение метода Mutatorа должно быть:

        public void setPrice(Double dbl) {

            if (dbl instanceof Double)

                price = dbl;

            else

                System.out.println("New Price could not be set!");

        }

 

То есть, если входной dbl имеет тип Double, то цена меняется. Если это не так, выдается сообщение об ошибке, и программа продолжает работу. Обратите внимание, что «d» для double в этом сегменте кода — это «D», а не «d».

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

        public void setCurrency(Character ch) {

            if (ch instanceof Character)

                currency = '€';

            else

                System.out.println("New currency is not a character!");

        }

 

То есть, если ввод ch имеет тип Character, то валюта изменяется с $ на ‘€’. Если это не так, выдается сообщение об ошибке, и программа продолжает работу. Обратите внимание, что «c» для символа в этом сегменте кода — это «C», а не «c».

 

Заключение

В Java нет предопределенного метода в качестве Mutatorа. Mutator кодируется программистом. Mutator — это просто закодированный (общедоступный) метод, который изменяет приватное значение поля (свойства) класса. С другой стороны, метод доступа — это просто закодированный (общедоступный) метод, который считывает частное значение поля (свойства) класса.

Спасибо, что прочитали нашу статью. Оставьте комментарий о своих мыслях и прочитайте другие статьи, которые лучше всего соответствуют идеям, которые вы ищете.



2022-04-01T16:00:06
Java

Алгоритм топологической сортировки

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

Каждый граф имеет более одной топологической последовательности сортировки, поскольку она зависит от степени вхождения ребер узлов. Первый начальный узел, который мы выбираем с числом узлов в степени, равен 0.

Давайте разберемся с алгоритмом топологической сортировки на примере.

Алгоритм топологической сортировки

 

Шаг 1: мы вставляем те узлы, количество входящих ребер которых равно 0. Таким образом, эти узлы являются узлами 1 и 4.

Алгоритм топологической сортировки

 

Шаг 2:

а. Начнем с узла 1. Мы можем выбрать любой узел между узлами 1 и 4.

б. Мы уменьшаем каждое ребро узла на 1, которое связано с узлом 1. Мы уменьшаем ребро узлов (0, 2 и 3).

в. Мы перемещаем узел 1 из списка в топологически отсортированный список, как показано ниже.

Алгоритм топологической сортировки

 

Шаг 3:

а. Теперь мы исходим из списка, который является Node 4.

б. Мы уменьшаем все исходящие ребра узлов, соединенных с узлом 4, которые являются узлами (0 и 3).

в. Теперь узел 3 не имеет входящих ребер, поэтому мы помещаем его в список, а узел 4 переходит в топологически отсортированный список.

Алгоритм топологической сортировки

 

Шаг 4:

а. Теперь мы исходим из списка, который является узлом 3.

б. Мы уменьшаем все исходящие ребра узлов, соединенных с узлом 3, которые являются узлами (0 и 2).

в. Теперь узлы 0 и 2 не имеют входящих ребер, поэтому мы помещаем их в список, а узел 3 переходит в топологически отсортированный список.

Алгоритм топологической сортировки

 

Шаг 5:

а. Теперь мы исходим из списка, который является Node 0.

б. Поскольку исходящих ребер из Node 0 нет, мы просто добавляем их в список топологической сортировки.

Алгоритм топологической сортировки

 

Шаг 6:

а. Теперь мы исходим из списка, который является узлом 2.

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

Алгоритм топологической сортировки

 

Шаг 7:

Наконец, мы отсортировали список здесь.

Алгоритм топологической сортировки

 

Алгоритм топологической сортировки

Ниже приведены шаги алгоритма топологической сортировки, которым мы должны следовать.

Шаг 0: Рассчитайте степень вхождения каждого узла графа.

Шаг 1: Сначала нам нужно найти узел, у которого входящие ребра равны нулю.

Шаг 2: мы удаляем этот узел из графа и добавляем его в список топологических порядков сортировки.

Шаг 3: Удалите те узлы, у которых есть исходящие ребра.

Шаг 4: Уменьшите степень вхождения на количество связанных ребер, которые были удалены.

Шаг 5: Повторяйте шаги 1–4, пока не останется узлов с нулевой степенью вхождения.

Шаг 6: Убедитесь, что все элементы расположены в правильной последовательности.

Шаг 7: Теперь мы отсортировали заказ из шага 6.

Шаг 8: Положите конец алгоритму.

 

Код Python : ниже приведена реализация приведенного выше примера на Python.

 

fromcollectionsimportdefaultdict



classbuildGraph :



def__init__(self, nodes : int) :

self.nodes= nodes



# Теперь мы сохраняем граф в формате смежного списка

self.adjListDetails=defaultdict(list)



# Он будет хранить информацию о входящих

ребрах определенного узла 



# в самом

self.count_numbers_of_incoming_edge_of_a_node= []



# Мы сохраняем отсортированные узлы в топологическом порядке

self.topological_sorted_order= []



# Мы храним информацию обо всех тех узлах, которые

# не имеют входящих ребер в графе

self.nodes_have_zero_incoming_edges= []



# Теперь мы создаем смежный список всех графов для сортировки

defAddGraphEdge (self, source :int, destination : int) :

self.adjListDetails[source].append(destination)

self.count_numbers_of_incoming_edge_of_a_node[destination] +=1



defTopologicalSortAlgorithm (self) :



for node inrange(self.nodes) :

ifself.count_numbers_of_incoming_edge_of_a_node[node] ==0 :

self.nodes_have_zero_incoming_edges.append(node)



whileself.nodes_have_zero_incoming_edges :

self.nodes_have_zero_incoming_edges.sort()

            source =self.nodes_have_zero_incoming_edges.pop(0)



# итерация по соседнему списку

if source inself.adjListDetails :

for node inself.adjListDetails[source] :

self.count_numbers_of_incoming_edge_of_a_node[node] -=1

ifself.count_numbers_of_incoming_edge_of_a_node[node] ==0 :

self.nodes_have_zero_incoming_edges.append(node)



self.topological_sorted_order.append(source)



print("Топологический порядок сортировки: "+str(self.topological_sorted_order))



defmain() :



number_of_nodes=7

    graph =buildGraph(number_of_nodes)

graph.count_numbers_of_incoming_edge_of_a_node= [0] *number_of_nodes



graph.AddGraphEdge(0,2)

graph.AddGraphEdge(0,5)

graph.AddGraphEdge(1,3)

graph.AddGraphEdge(1,6)

graph.AddGraphEdge(2,4)

graph.AddGraphEdge(3,5)

graph.AddGraphEdge(5,2)

graph.AddGraphEdge(5,4)

graph.AddGraphEdge(6,2)



graph.TopologicalSortAlgorithm()



if __name__ =="__main__" :

main()

 

 

Выход:

Топологический порядок сортировки: [0, 1, 3, 5, 6, 2, 4]

 

Временная сложность алгоритма топологической сортировки:

Общее время обработки алгоритма равно O (E + N), где E представляет количество ребер, а N представляет количество узлов в графе. Затем, на следующем шаге, мы должны вычислить степень входа каждого узла, что обычно занимает O(E) раз, а затем поместить все эти узлы в отсортированный список, где их степень входа равна нулю, что занимает O(N) раз. раз. Таким образом, общая временная сложность алгоритма топологической сортировки составляет O (E+N).

Но пространственная сложность алгоритма топологической сортировки составляет O (N), что равно общему количеству узлов в графе.

 

Применение:

  1. Топологическая сортировка очень полезна для нахождения цикла графа.
  2. Алгоритм топологической сортировки используется для определения условий взаимоблокировки в операционной системе.
  3. Алгоритм топологической сортировки используется для поиска кратчайшего пути во взвешенном ациклическом графе.

 

Вывод :

В этой статье мы узнали еще об одном важном алгоритме — топологической сортировке. Мы видели, что этот алгоритм работает только с ациклическими графами. Алгоритм топологической сортировки также помогает определить порядок составления задачи. Алгоритм топологической сортировки имеет много преимуществ в реальном времени, например поиск кратчайшего пути. Поскольку топологическая сортировка чрезвычайно полезна, каждый программист и студент должен хорошо понимать этот алгоритм.



2022-03-19T18:03:01
Программирование

Алгоритм Прима

Минимальное связующее дерево:

Граф, не имеющий направлений, называется неориентированным графом. Каждый граф должен иметь путь от одного узла к другому узлу. Остовное дерево также является неориентированным связным графом, в котором присутствуют все узлы графа с минимальным количеством ребер. Если остовное дерево не имеет всех узлов графа, то мы не можем сказать, что это остовное дерево. Суммарные веса остовного дерева будут меньше исходного веса графа, так как мы соединили его через ребра минимального веса. Покрывающее дерево также не имеет цикла. Любой граф имеет более одного остовного дерева, но только одно из них будет уникальным. Мы называем это минимальным остовным деревом, поскольку пытаемся создать полный граф со всеми узлами, сохраняя при этом низкий вес.

Мы можем нарисовать остовное дерево с помощью следующих двух методов:

  1. Алгоритм Крускала
  2. Алгоритм Прима

 

В этой статье мы собираемся обсудить алгоритм Прима. Алгоритм Крускала будет рассмотрен в следующей статье.

 

Алгоритм Прима:

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

 

Шаги алгоритма Прима:

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

  • Шаг 1: Выберите любую исходную вершину в графе.
  • Шаг 2: Найдите ребро минимального веса, которое примыкает к источнику, а затем соедините его с остовным деревом.
  • Шаг 3: Повторяйте шаг 2, пока все узлы не будут добавлены в минимальное остовное дерево.

 

Пример :

Ниже приведен пример поиска минимального остовного дерева с использованием алгоритма Прима.

1. Выбираем любой случайный узел из графа G и добавляем его в MST (минимальное остовное дерево). Мы выбираем здесь узел 0.

Алгоритм Прима

 

2. Теперь мы выбираем то ребро, которое является смежным с исходным узлом (0), но с наименьшим весом, а затем добавляем этот узел с наименьшим весом в минимальное остовное дерево.

Алгоритм Прима

 

3. Теперь мы выбираем то ребро, которое является смежным с исходным узлом (0 или 1), но с наименьшим весом, а затем добавляем этот узел с наименьшим весом в минимальное остовное дерево.

Алгоритм Прима

 

4. Теперь мы выбираем то ребро, которое является смежным с исходным узлом (0, 1 или 3), но с наименьшим весом, а затем добавляем этот узел с наименьшим весом в минимальное остовное дерево.

Алгоритм Прима

 

5. Теперь мы выбираем то ребро, которое является смежным с исходным узлом (0, 1, 3 или 4), но с наименьшим весом, а затем добавляем этот узел с наименьшим весом в минимальное остовное дерево.

Алгоритм Прима

 

6. Теперь мы выбираем то ребро, которое является смежным с исходным узлом (0, 1, 3, 4 или 6), но с наименьшим весом, а затем добавляем этот узел с наименьшим весом в минимальное остовное дерево.

Алгоритм Прима

 

7. Теперь мы выбираем то ребро, которое является смежным с исходным узлом (0, 1, 3, 4, 6 или 2), но с наименьшим весом, а затем добавляем этот узел с наименьшим весом в минимальное остовное дерево.

Алгоритм Прима

 

Выше наш окончательный MST (минимальное остовное дерево), а общая стоимость равна 6.

 

Программа C++ Prim MST (минимальное связующее дерево):

#include<iostream>



#include<vector>



#include<queue>



#include<algorithm>



#include<cstring>



typedef std :: pair<int,int> SII;



typedef std :: vector<SII> SSII;



int PrimsMST (int sourceNode, std :: vector<SSII> & graph){



    // В этой очереди будут храниться сведения о каждом узле

    // вместе с их весовой ценностью.



    std :: priority_queue<SII, std :: vector<SII>, std :: greater<SII>> k;



 



    k.push(std :: make_pair(0, sourceNode));



    bool nodesAdded[graph.size()];



    memset(nodesAdded, false, sizeof(bool)*graph.size());



    int mst_tree_cost = 0;



    while (!k.empty()) {



        // We are selecting here the node which has minimum cost



        SII itemNode;



        itemNode = k.top();



        k.pop();



        int Node = itemNode.second;



        int Cost = itemNode.first;



        // Здесь мы проверяем, не был ли какой-либо узел добавлен в MST,



        // затем добавляем этот узел.



        if (!nodesAdded[Node]) {



            mst_tree_cost += Cost;



            nodesAdded[Node] = true;



            // Выполните итерацию по узлам negibour, которые недавно были удалены



            // из очереди приоритетов.



            // и добавлен в MST, который еще не добавлен



            for (auto & pair_node_cost : graph[Node]) {



                int adjency_node = pair_node_cost.second;



                if (nodesAdded[adjency_node] == false) {



                    k.push(pair_node_cost);



                }



            }



        }



    }



    return mst_tree_cost;



}



    int main(){



    // Подробная информация о графике со стоимостью и узлом смежности.



    SSII fromNode_0_in_graph_1  = { {1,1}, {2,2}, {1,3},



    {1,4}, {2,5}, {1,6} };



    SSII fromNode_1_in_graph_1   = { {1,0}, {2,2}, {2,6} };



    SSII fromNode_2_in_graph_1   = { {2,0}, {2,1}, {1,3} };



    SSII fromNode_3_in_graph_1 = { {1,0}, {1,2}, {2,4} };



    SSII fromNode_4_in_graph_1  = { {1,0}, {2,3}, {2,5} };



    SSII fromNode_5_in_graph_1  = { {2,0}, {2,4}, {1,6} };



    SSII fromNode_6_in_graph_1   = { {1,0}, {2,2}, {1,5} };



    int num_of_nodes = 7; // Total Nodes (0 to 6)



    std :: vector<SSII> primsgraph;



    primsgraph.resize(num_of_nodes);



    primsgraph[0] = fromNode_0_in_graph_1;



    primsgraph[1] = fromNode_1_in_graph_1;



    primsgraph[2] = fromNode_2_in_graph_1;



    primsgraph[3] = fromNode_3_in_graph_1;



    primsgraph[4] = fromNode_4_in_graph_1;



    primsgraph[5] = fromNode_5_in_graph_1;



    primsgraph[6] = fromNode_6_in_graph_1;



    // Как мы уже знаем, мы должны выбрать исходную вершину,



    // поэтому мы начинаем с узла вершины 0.



    std :: cout << "Общая стоимость минимального связующего дерева после алгоритма Прима : "



                "" << PrimsMST(0, primsgraph) << std :: endl;





    return 0;



}

Выход:

Общая стоимость минимального связующего дерева после алгоритма Прима : 6



Process finished with exit code 0

Временная сложность алгоритма MST Prim:

  1. Общее время, необходимое для обработки и выбора определенного узла очереди с приоритетом, который еще не добавлен в MST, составляет logV. Но поскольку это работает для каждой вершины, общая временная сложность составляет V (logV).
  2. Граф неориентированный, и общее количество ребер будет 2E. Поскольку мы должны поместить узлы в приоритетную очередь, это займет журнал общего времени (V). Однако, поскольку у нас есть в общей сложности 2E ребра, наша общая операция отправки будет 2E (log (V)).
  3. Общая сложность после операции 1 и 2 составляет O( (E + V ) log (V )).

 

Заключение:

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



2022-03-10T18:08:39
Программирование

Приоритетная очередь в Java

Предположим, что вы предлагаете услуги трем разным людям, стоящим перед вами. Третий человек оказывается вашим другом. Услуга должна быть обслужена в порядке очереди. При использовании принципа «первым пришел — первым обслужен» первый человек имеет наибольший приоритет; второй человек имеет больший приоритет; третье лицо, меньший приоритет и так далее. Вас не накажут, если вы не соблюдаете принцип «первым пришел — первым обслужен». Вы решили сначала обслужить своего друга, затем первого человека, а затем второго человека. Это означает, что вы отдали своему другу наивысший приоритет. Если смотреть на сценарий с точки зрения робота, то третья позиция имела наибольший приоритет.

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

На третий день ваш друг становится первым, и вы действуете по принципу «первым пришел — первым обслужен». Вывод любого и робота состоит в том, что приоритет зависит от того, кого это касается, и от позиции каждого человека. Примечание: в реальной жизни приоритет не всегда зависит от принципа «первым пришел — первым обслужен».

В программировании очередь с двоичным приоритетом — это очередь, в которой первый элемент имеет наибольший приоритет. Третий элемент может иметь больший приоритет, а второй элемент — третий приоритет. Очереди приоритетов имеют бинарную природу. Примечание: первый элемент всегда имеет наивысший приоритет в очереди приоритетов. Также может случиться так, что второй элемент имеет больший приоритет, а третий элемент имеет третий приоритет. В определении очереди приоритетов приоритеты второго и третьего элементов могут быть не в порядке убывания. Эта разница продолжается вниз по очереди до последнего элемента, который не может быть элементом с наименьшим приоритетом. Однако он будет одним из наименее приоритетных. Эта частичная сортировка также известна как частичная сортировка. Итак, очередь с приоритетом — это очередь с частичным порядком, где приоритет не «первым пришел — первым обслужен»,

При работе с массивом «первым пришел — первым обслужен» является «первым поступил — первым обслужен», записывается как FIFO. В вычислениях очередь — это FIFO, а очередь с приоритетом — частичная FIFO, потому что по мере убывания очереди некоторые элементы имеют более высокие приоритеты, чем их ближайшие предшественники. По мере дальнейшего опускания очереди приоритетов расстояние между такими ближайшими предшественниками и более высокими приоритетами увеличивается.

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

 

Структура данных кучи

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

Двоичная куча — это место, где узел (элемент) имеет двух дочерних элементов. Первый ребенок — левый ребенок, а второй ребенок — правый ребенок. Значение любого узла называется ключом.

 

Max-Heap

Следующий список представляет собой максимальную кучу, которая уже частично упорядочена и не нуждается в дальнейшем упорядочении:

89, 85, 87, 84, 82, 79, 73, 80, 81, , , 65, 69

 

89 — первое значение с индексом 0. Это корневой узел (корневой родитель). Это самая большая ценность среди всех ценностей. Его первый потомок (85) имеет индекс 1, индекс которого равен 2(0) + 1, где 0 — индекс родителя. Его второй потомок (87) имеет индекс 2, что равно 2(0) + 2, где 0 — индекс родителя.

85 находится в индексе 1. Это родитель. Его первый потомок (84) имеет индекс 3, что равно 2(1) + 1, где 1 — индекс родителя. Его второй потомок (82) имеет индекс 4, что равно 2(1) + 2, где 1 — индекс родителя.

87 находится в индексе 2. Это родитель. Его первый потомок (79) имеет индекс 5, что равно 2(2) + 1, где 2 — индекс родителя. Его второй потомок (73) имеет индекс 6, что равно 2(2) + 2, где 2 — индекс родителя.

В общем, поскольку подсчет индексов начинается с 0, пусть i представляет индекс родителя массива; и, таким образом, левый (первый) потомок родителя с индексом i имеет индекс 2i + 1; а его правый (второй) дочерний элемент имеет индекс 2i + 2. Некоторые ячейки ближе к концу массива могут быть пустыми; они не должны иметь значений.

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

 

Min-Heap

Min-heap — это обратная сторона max-heap.

 

Приоритетная очередь в Java

В Java есть класс PriorityQueue для Priority-Queue. Он имеет множество конструкторов и методов. Ниже описаны только три конструктора и более подходящие методы:

 

Создание очереди приоритетов в Java

Public PriorityQueue()

Это создает приоритетную очередь без какого-либо элемента. Класс PriorityQueue находится в пакете java.util.*, который необходимо импортировать. Следующий сегмент кода создает пустую PriorityQueue, а затем добавляет в очередь несортированные (даже частично не отсортированные) значения:

PriorityQueue<Integer> pq = new PriorityQueue<Integer>();



pq.add(69); pq.add(65); pq.add(87); pq.add(79);



pq.add(73); pq.add(84); pq.add(89); pq.add(80);



pq.add(81); pq.add(82); pq.add(85);

 

Все эти числа целые. Они взяты из частично отсортированного списка, приведенного выше, но в настоящее время они полностью не отсортированы по мере ввода. Элементы в pq теперь частично отсортированы в соответствии с определением приоритетной очереди в Java.

 

Public PriorityQueue(PriorityQueue<? extends E> c)

Это создает приоритетную очередь из другой приоритетной очереди. Следующий сегмент кода иллюстрирует это:

PriorityQueue<Integer> pq = new PriorityQueue<Integer>();



pq.add(69); pq.add(65); pq.add(87); pq.add(79);



pq.add(73); pq.add(84); pq.add(89); pq.add(80);



pq.add(81); pq.add(82); pq.add(85);



PriorityQueue<Integer> pq1 = new PriorityQueue<Integer>(pq);

 

pq1 был создан из pq. В настоящее время он имеет тот же частичный порядок и pq.

Третий метод конструктора показан ниже.

 

Java-методы приоритетной очереди

Public Int Size()

Это возвращает размер списка и не включает пустые ячейки, как показано в следующем коде:

PriorityQueue<Integer> pq = new PriorityQueue<Integer>();



pq.add(69); pq.add(65); pq.add(87); pq.add(79);



pq.add(73); pq.add(84); pq.add(89); pq.add(80);



pq.add(81); pq.add(82); pq.add(85);



int sz = pq.size();



System.out.println(sz);

 

Вывод 11.

 

Public Void forEach(Consumer<? super E> action)

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

PriorityQueue<Integer> pq = new PriorityQueue<Integer>();



pq.add(69); pq.add(65); pq.add(87); pq.add(79);



pq.add(73); pq.add(84); pq.add(89); pq.add(80);



pq.add(81); pq.add(82); pq.add(85);



pq.forEach (item -> System.out.print(item + " "));



System.out.println();



Обратите внимание на то, как сделан код в скобках метода forEach. Элемент — это фиктивная переменная, которая представляет каждый элемент в очереди. Обратите внимание на использование оператора стрелки. Результат:

65 69 84 79 73 87 89 80 81 82 85

 

Вывод правильный, в частичном порядке, но в порядке возрастания. Это не обязательно обратный порядок, указанный выше, из-за способа включения значений в список. То есть метод forEach возвращает список в виде минимальной кучи. Чтобы вернуть список в порядке убывания, используйте следующий конструктор:

 

Public PriorityQueue(Comparator<? super E> comparator)

Это конструктор. Следующий код показывает, как его использовать:

PriorityQueue<Integer> pq = new PriorityQueue<Integer>((x, y) -> Integer.compare(y, x));



pq.add(69); pq.add(65); pq.add(87); pq.add(79);



pq.add(73); pq.add(84); pq.add(89); pq.add(80);



pq.add(81); pq.add(82); pq.add(85);



pq.forEach (item -> System.out.print(item + " "));

 

X, y — фиктивные переменные, представляющие меньшее и меньшее значения. Обратите внимание, что в первых скобках для x и y x стоит перед y. Во вторых скобках y стоит перед x. Результат:

89 85 87 80 82 69 84 65 79 73 81

Public Boolean Add(E e)

Количество элементов в приоритетной очереди можно увеличивать по одному. Этот метод возвращает true, если изменение произошло; и ложно в противном случае. Следующий код добавляет в очередь двенадцатое практическое значение:

PriorityQueue<Integer> pq = new PriorityQueue<Integer>((x, y) -> Integer.compare(y, x));



pq.add(69); pq.add(65); pq.add(87); pq.add(79);



pq.add(73); pq.add(84); pq.add(89); pq.add(80);



pq.add(81); pq.add(82); pq.add(85); pq.add(70);



pq.forEach (item -> System.out.print(item + " "));

 

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

89 85 87 80 82 70 84 65 79 73 81 69

Public E Poll()

Этот метод извлекает и удаляет голову очереди; или возвращает null, если эта очередь пуста. Каждый раз, когда голова удаляется, приоритетная очередь перестраивается, чтобы иметь новую законную голову. Если головка продолжает удаляться, возвращаемые значения будут полностью отсортированы. Следующий код иллюстрирует это:

PriorityQueue<Integer> pq = new PriorityQueue<Integer>((x, y) -> Integer.compare(y, x));



pq.add(69); pq.add(65); pq.add(87); pq.add(79);



pq.add(73); pq.add(84); pq.add(89); pq.add(80);



pq.add(81); pq.add(82); pq.add(85); pq.add(70);



pq.forEach (item -> System.out.print(pq.poll() + " "));

 

Вывод:

89 87 85 84 82 81 80 79 73 70 69 65 Exception in thread "main" java.util.ConcurrentModificationException



at java.base/java.util.PriorityQueue.forEach(PriorityQueue.java:984)



at TheClass.main(TheClass.java:11)

 

Обратите внимание, что вывод имеет полный отсортированный порядок. Этот конкретный код не смог перехватить выброшенное исключение. Этот вопрос оставлен читателю в качестве исследовательского упражнения.

 

Заключение

Очередь с приоритетом в Java — это очередь, в которой элементы имеют приоритет, отличный от FIFO. Очередь с приоритетом обычно представляет собой кучу, которая может быть максимальной или минимальной. Значения должны быть одного типа. Они хранятся в очереди в формате кучи (частичный порядок). Мы надеемся, что вы нашли эту статью полезной. Ознакомьтесь с другими статьями Linux Hint, чтобы получить советы и руководства.



2022-02-19T10:06:28
Java