Как найти сумму элементов динамического массива

DenisKrut

6 / 6 / 9

Регистрация: 18.03.2014

Сообщений: 176

1

Динамический массив, найти сумму элементов

01.02.2015, 00:16. Показов 9671. Ответов 8

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Помогите пожалуйста.В одномерном массиве состоящем из n целых элементов, вычислить.
Сумму модулей элементов массива, расположенных после первого элемента, равного 0

Добавлено через 6 минут

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <windows.h>
#include <wincon.h>
#pragma hdrstop
 
#pragma argsused
int main()
{ SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
  cout << "Ââåäèòå êîëè÷åñòâî ýëåìåíòîâ ";
  int n,sum;
  cin >> n;
  int *a=new int[n];
  srand(time(NULL));
  for (int i=0; i<n; i++)
  {a[i]=rand()%100-rand()%100;
  cout << a[i] << " ";}
  for (int i=0; i<n; i++)
  sum=a[0];
  {if (a[i]=0);
  sum=sum+abs(a[i]) ;}
  cout << endl;
  cout << "Ñóììó ìîäóëåé ýëåìåíòîâ ìàññèâà = "<<sum;
  delete[] a;
  getch();
  return 0;
}



0



hoggy

Эксперт С++

8724 / 4304 / 958

Регистрация: 15.11.2014

Сообщений: 9,751

01.02.2015, 00:33

2

http://rextester.com/ZKNOIZ85999

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <cstdlib> 
#include <vector> 
#include <ctime>   
 
using namespace std;
 
int main()
{
    std::srand ( unsigned ( std::time(0) ) );
    
    std::cout << "Hello, world!n";
    
    const int ar[]={0,1,2,3,4,5,6,7,8,9};
    
    std::vector<int>
        myvector(ar, ar+10);
    
    std::ostream_iterator<int> 
        out(std::cout,", ");
    
    std::cout<<"result = " << (
            std::random_shuffle( myvector.begin(), myvector.end() ),
            
            std::copy(myvector.begin(), myvector.end(), out ),
            
            std::accumulate(
                std::find( myvector.begin(), myvector.end(), 0 ),
                myvector.end(), 0
            )
        ) << std::endl;
}



0



ivan.-94

Я Фоюмчанин ? дааааа)

213 / 204 / 23

Регистрация: 02.06.2012

Сообщений: 1,424

Записей в блоге: 12

01.02.2015, 17:09

3

Вы бы хоть попытались разобраться
Совет на будущее – первым делом приведите код в порядок))

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream.h>
#include <conio.h>
#include <windows.h>
#pragma hdrstop
 
#pragma argsused
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    cout << "Введите количество элементов ";
    int n,sum;
    cin >> n;
    int *a=new int[n];
    srand(time(NULL));
    for (int i=0; i<n; i++)
    {
        a[i]=rand()%100-rand()%100;
        cout << a[i] << " ";
    }
    sum=a[0];
    for (int i=1; i<n; i++)
    {
        if (a[i]==0);
        sum += abs(a[i]);
    }
    cout << endl;
    cout << "Сумму модулей элементов массива = "<<sum;
    delete[] a;
    getch();
    return 0;
}



0



TaiGeddar

6 / 6 / 6

Регистрация: 13.01.2014

Сообщений: 110

01.02.2015, 17:15

4

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<cstdlib>
using namespace std;
 
int main()
{
    int n=rand()%99; //случайное количество
    int *m=new int [n];//инициализация динамического массива
    int k=0;
    for (int i=0; i<=n; i++)
    {
        m[i]=(rand()%33) - (rand()%33);//задание значения  
    }
    
    for(int i=0; i<=n; i++)
    {
        
if (m[i]==0){
    k+=abs(m[i]);//нахождение суммы модулей 
}   
}
    cout<<"k="<<k<<endl;
    return 0;
}

Пардон, меня опередили.

Добавлено через 5 минут
ivan.-94, а разве abs работает без math.h?



1



Я Фоюмчанин ? дааааа)

213 / 204 / 23

Регистрация: 02.06.2012

Сообщений: 1,424

Записей в блоге: 12

01.02.2015, 17:17

5

Цитата
Сообщение от TaiGeddar
Посмотреть сообщение

ivan.-94, а разве abs работает без math.h?

Да, работает.



0



6 / 6 / 6

Регистрация: 13.01.2014

Сообщений: 110

01.02.2015, 17:21

6

ivan.-94, знаешь… я идиот упоротый, я хотел спросить работает ли rand() без cstdlib.
DEV без cstdlib ругается.



0



Я Фоюмчанин ? дааааа)

213 / 204 / 23

Регистрация: 02.06.2012

Сообщений: 1,424

Записей в блоге: 12

01.02.2015, 17:29

7

Да и abs определена в stdlib.h, но в этом проекте пока не убрал этот заголовочный – abs не работал.

Добавлено через 5 минут
У меня кстати достаточно странно себя ведет компилятор – но этот abs не всегда срабатывает
как то через раз, но под дебагом все четко.

Добавлено через 26 секунд
TaiGeddar, У меня работает))



0



6 / 6 / 6

Регистрация: 13.01.2014

Сообщений: 110

01.02.2015, 17:37

8

ivan.-94,

Цитата
Сообщение от ivan.-94
Посмотреть сообщение

sum=a[0];

a[0] может быть не нуливым, а ты его прибавляешь. Ошибся или я что-то не так понял?

Добавлено через 3 минуты
ivan.-94, мы оба не верно решили.
Нужно найти элемент равный нулю и после него все сложить.



0



ivan.-94

Я Фоюмчанин ? дааааа)

213 / 204 / 23

Регистрация: 02.06.2012

Сообщений: 1,424

Записей в блоге: 12

01.02.2015, 17:44

9

Лучший ответ Сообщение было отмечено DenisKrut как решение

Решение

TaiGeddar, Да вы почти правы, только не в ту сторону))
Нужно просто взять по модулю sum=abs(a[0]); – если нулевой не важно, главное что бы не отрицательный.
И мы не правильно решили))) там добавить все го то 1 цикл перед суммированием))

Добавлено через 5 минут

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream.h>
#include <conio.h>
#include <windows.h>
#pragma hdrstop
 
#pragma argsused
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    cout << "Введите количество элементов ";
    int n, sum=0;
    cin >> n;
    int *a=new int[n];
    srand(time(NULL));
    for (int i=0; i<n; i++)
    {
        a[i]=rand()%100-rand()%100;
        cout << a[i] << " ";
    }
    int iterNull = 0;
    while (a[iterNull]!=0) iterNull++;
    for (int i=iterNull; i<n; i++)
    {
        if (a[i]==0);
        sum += abs(a[i]);
    }
    cout << endl;
    cout << "Сумму модулей элементов массива = "<<sum;
    delete[] a;
    getch();
    return 0;
}



1



Обычно, объем памяти, необходимый для той или иной переменной, задается еще до процесса компиляции посредством объявления этой переменной. Если же возникает необходимость в создание переменной, размер которой неизвестен заранее, то используют динамическую память. Резервирование и освобождение памяти в программах на C++ может происходить в любой момент времени. Осуществляются операции распределения памяти двумя способами:

  • с помощью функции malloc, calloc, realloc и free;
  • посредством оператора new и delete.

Функция malloc резервирует непрерывный блок ячеек памяти для хранения указанного объекта и возвращает указатель на первую ячейку этого блока. Обращение к функции имеет вид:

void *malloc(size);

Здесь size — целое беззнаковое значение, определяющее размер выделяемого участка памяти в байтах. Если резервирование памяти прошло успешно, то функция возвращает переменную типа void *, которую можно привести к любому необходимому типу указателя.

Функция — calloc также предназначена для выделения памяти. Запись ниже означает, что будет выделено num элементов по size байт.

void *calloc (nime, size);

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

Функция realloc изменяет размер выделенной ранее памяти. Обращаются к ней так:

char *realloc (void *p, size);

Здесь p — указатель на область памяти, размер которой нужно изменить на size. Если в результате работы функции меняется адрес области памяти, то новый адрес вернется в качестве результата. Если фактическое значение первого параметра NULL, то функция realloc работает также, как и функция malloc, то есть выделяет участок памяти размером size байт.

Для освобождения выделенной памяти используется функция free. Обращаются к ней так:

void free (void *p size);

Здесь p — указатель на участок памяти, ранее выделенный функциями malloc, calloc или realloc.

Операторы new и delete аналогичны функциям malloc и free. New выделяет память, а его единственный аргумент — это выражение, определяющее количество байтов, которые будут зарезервированы. Возвращает оператор указатель на начало выделенного блока памяти. Оператор delete освобождает память, его аргумент — адрес первой ячейки блока, который необходимо освободить.

Динамический массив — массив переменной длины, память под который выделяется в процессе выполнения программы. Выделение памяти осуществляется функциями calloc, malloc или оператором new. Адрес первого элемента выделенного участка памяти хранится в переменной, объявленной как указатель. Например, следующий оператор означает, что описан указатель mas и ему присвоен адрес начала непрерывной области динамической памяти, выделенной с помощью оператора new:

int *mas=new int[10];

Выделено столько памяти, сколько необходимо для хранения 10 величин типа int.

Фактически, в переменной mas хранится адрес нулевого элемента динамического массива. Следовательно, адрес следующего, первого элемента, в выделенном участке памяти — mas+1, а mas+i является адресом i-го элемента. Обращение к i-му элементу динамического массива можно выполнить, как обычно mas[i], или другим способом *(mas +i). Важно следить за тем, чтобы не выйти за границы выделенного участка памяти.

Когда динамический массив (в любой момент работы программы) перестает быть нужным, то память можно освободить с помощью функции free или оператора delete.

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

Задача 1

Найти сумму вещественных элементов динамического массива.

//Пример использования функции malloc и free
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
setlocale(LC_ALL,"Rus");
int i, n;
float *a; //указатель на float
float s;
cout<<"n"; cin>>n; //ввод размерности массива
//выделение памяти под массив из n вещественных элементов
a=(float *)malloc(n*sizeof(float));
cout<<"Введите массив A n";
//ввод элементов массива
for (i=0; i<n; i++)
{
cin>>*(a+i);
}
//накапливание суммы элементов массива
for (s=0, i=0; i<n; i++)
s+=*(a+i);
//вывод значения суммы
cout<<"S="<<s<<"n";
//освобождение памяти
free(a);
system("pause");
return 0;
}

Задача 2

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

//Пример использования операторов new и delete
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
setlocale(LC_ALL,"Rus");
int i, n;
//ввод количества элементов массива
cout<<"n="; cin>>n;
//выделение памяти
int *a=new int[n];
cout<<"Введите элементы массива:n";
//ввод массива
for (i=0; i<n; i++)
cin>>a[i];
//вывод заданного массива
for (i=0; i<n; i++)
cout<<a[i]<<"t"<<"n";
//преобразование массива
for (i=0; i<n; i++)
a[i]=-a[i];
//вывод преобразованного массива
for (i=0; i<n; i++)
cout<<a[i]<<"t"; cout<<"n";
//освобождение памяти
delete []a;
system("pause");
return 0;
}

printf(“По адресу p1=%p хранится *p1=%gn”,p1,*p1); printf(“По адресу p2=%p хранится *p2=%en”,p2,*p2);

}

По адресу p1=0012FF7C хранится *p1=3.14159

По адресу p2=0012FF7C хранится *p2=2.642140e-308

В указателях p1 и p2 хранится один и тот же адрес, но значения, на которые они ссылаются, оказываются разными. Это связано с тем, указатель типа *float адресует 4 байта, а указатель *double 8байт .После присваивания p2=(double *)p1;при обращении к *p2происходит следующее: к переменной, хранящейся по адресу p1, дописывается еще 4 байта из памяти. В результате значение *p2 не совпадает со значением *p1.

А что произойдет в результате следующей программы?

#include <stdio.h> #include <math.h> int main()

{

double PI=3.14159,*p1; float *p2;

p1=&PI; p2=(float *)p1;

printf(“По адресу p1=%p хранится *p1=%gn”,p1,*p1); printf(“По адресу p2=%p хранится *p2=%en”,p2,*p2);

}

После присваивания p2=(double *)p1; при обращении к *p2 происходит следующее: из переменной, хранящейся по адресу p1, выделяется только 4 байта. В результате и в этом случае значение *p2 не совпадает со значением *p1.

ВЫВОД. При преобразовании указателей разного типа приведение типов разрешает только синтаксическую проблему присваивания. Следует помнить, что операция * над указателями различного типа, ссылающимися на один и тот же адрес, возвращает различные значения.

Если есть следующий оператор

float *p;

то в переменной p хранится адрес, а с помощью конструкции *p можно получить значение, хранящееся по адресу p.

В случае использования оператора

float p;

то для вычисления адреса используется конструкция &p, а в переменной p находится вещественное значение.

Над адресами в языке Си определены следующие операции:

суммирование, можно добавлять к указателю целое значение;

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

double *p1; float *p2; int *i;

p1++

p2++;

i++;

}

Операция p1++ увеличивает значение адреса на 8, операция p2++ увеличивает значение адреса на 4, а операция i++ на 2. Операции адресной арифметики выполняются следующим образом:

операция увеличения приводит к тому, что указатель будет слаться на следующий объект базового типа (для p1 это double,для p2 float,для i int);

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

после операции p1=p1+n, указатель будет передвинут на n объектов базового типа; p1+n как бы адресует n-й элемент массива, если p1 адрес начала массива .

5.4.5. Использование адресов и указателей при работе с массивами. Динамические массивы.

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

1.Описать указатель (например, переменную p) определенного типа.

2.Начиная с адреса, определенного указателем, с помощью функций calloc, malloc или операции new выделить участок памяти определенного размера. После этого p будет адресом первого элемента выделенного участка оперативной памяти (0-й элемент массива), p+1 будет адресовать следующий элемент в выделенном участке памяти (1-й элемент динамического массива), & , p+i является адресом i-го элемента.

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

*(p+i) или p[i].

3.Когда участок памяти будет не нужен, его можно освободить с помощью функции free(), операции delete.

Перед подробным описанием работы с динамическими переменными, рассмотрим функции calloc, malloc, realloc и free и операции new и delete.

Единственным параметром функции malloc является целое беззнаковое значение, определяющее размер выделяемого участка памяти в байтах. Функция malloc возвращает бестиповый указатель (void *) на выделенный участок памяти. Обращение к функции malloc имеет вид

void *malloc(n);

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

В качестве примера использования функции malloc решим следующую задачу.

Найти сумму элементов динамического массива вещественных чисел.

#include <iostream> #include <malloc.h> using namespace std; int main()

{

int i,n; float *a,s;

cout<<“n=”;

cin>>n;

// Выделение памяти для динамического массива а. a=(float *)malloc(n*sizeof(float));

cout << “Vvedite massiv A”; for(i=0;i<n;i++)

// cin>>a[i]; cin>>*(a+i);

for(s=0,i=0;i<n;i++)

//s+=a[i];

s+=*(a+i); cout << “S=”<<s;

//Освобождение памяти. free(a);

return 0;

}

Кроме функции malloc для выделения памяти в Си есть функция calloc. Ее особенностью является обнуление всех выделенных элементов. Обращение к функции имеет вид:

void *calloc (num, size);

Функция calloc выделяет num элементов по size байт и возвращает указатель на выделенный участок или NULL при невозможности выделить память.

Ниже приведено решение задачи поиска суммы элементов динамического массива

вещественных чисел с помощью функции calloc.

#include <iostream> #include <malloc.h> using namespace std; int main()

{

int i,n; float *a,s; cout<<“n=”; cin>>n;

// Выделение памяти для динамического массива а. a=(float *)calloc(n,sizeof(float));

cout << “Vvedite massiv A”; for(i=0;i<n;i++)

cin>>*(a+i);

for(s=0,i=0;i<n;i++)

s+=*(a+i); cout << “S=”<<s;

//Освобождение памяти. free(a);

return 0;

}

Функция realloc изменяет размер выделенной ранее памяти, обращение к ней имеет вид:

char *realloc(void *p, size);

Функция изменяет размер участка памяти, на который указывает p, новый размер участка памяти size. Если при этом пришлось изменять месторасположение участка памяти, то новое его месторасположение и возвращается в качестве результата. Если в качестве p передается NULL, то функция realloc работает аналогично функции malloc.

Для освобождения выделенной памяти используется функция free. Обращение к ней имеет вид

Соседние файлы в предмете Программирование на C++

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Работа с динамическими массивами в Паскаль abc.net

Содержание:

  • Динамические массивы
    • Объявление, выделение памяти
    • Инициализация, присваивание и вывод
    • Вывод массива
    • Очистка динамического массива
    • Работа с элементами массива
    • Методы для работы с массивами
    • Некоторые алгоритмы работы с массивами
  • Срезы
  • Удаление и вставка элементов массива. Списки
  • Решение задач
    • Простые задачи
    • Задачи на срезы
    • Использование методов

Динамические массивы

Объявление, выделение памяти

Обычно в языке Паскаль используются статические массивы вида:

var mas: array [1..10] of integer;

Границы статического массива изменить в ходе программы нельзя, так как они задаются в разделе объявлений «раз и навсегда».
Основным недостатком такого массива является то, что в случае, когда заранее не известно количество элементов массива, то приходится выделять память максимального размера, что называется «на всякий случай».

Рассмотрим работу с динамическим массивом.

Объявляется динамический массив в теле программы:

begin
...
var a: array of integer;

Или объявление с инициализацией:

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

  1. var a: array of integer;
    var n:=readInteger;
    a:=new integer[n];
  2. var a: array of integer;
    a:=new integer[readInteger];
  3. var a: array of integer;
    var n:=readInteger;
    SetLength(a,n); // устанавливаем размер массива а
  4. Ссылочная объектная модель: память выделяется служебным словом NEW

Организация памяти для массива a

Организация памяти для массива a

Инициализация, присваивание и вывод

Возможна инициализация динамического массива при описании:

var a: array of integer := (1,2,3);

Новые способы заполнения массива (заполнители):

var a:=Arr(1,2,3);// по правой части - integer
var a:=ArrFill(5,2); // 2 2 2 2 2

Ввод с клавиатуры:

var a:=ReadArrInteger(5); 
var a:=ReadArrReal(5);

Заполнение случайными числами:

var a:=new integer[10];
a:=arrRandomInteger(10);

или с дополнительными параметрами (диапазон [5;15]):

var a:=arrRandomInteger(10,5,15);

Вывод массива

Или с разделителем между элементами:

Или:

Или с использованием метода:

a.Print; // пример вывода: 1 5 3 13 20
a.PrintLines; // каждый элемент с новой строки

Переприсваивание:

var a: array of integer := (1,2,3);
var b:=a; // [1,2,3]

ссылочная объектная модель
Но!
Если теперь переприсвоить значение элементов массива b, то изменится и массив a:

var a: array of integer := (1,2,3);
var b:=a;
b[2]:=1;
print(a); //[1,2,1]

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

var a: array of integer := (1,2,3);
var b:=Copy(a);
b[2]:=1;
print(a); //[1,2,3]

Очистка динамического массива

Если в программе случайно создается повторно один и тот же массив:

var a: array of integer;
a:=new integer[4];
...
a:=new integer[5];

очистка пямяти паскаль abc net
В результате возникают так называемые участки «утекшей» памяти (неиспользуемой).
Постепенно произойдет переполнение памяти. В платформе .net используется автоматический сборщик мусора.

Но можно очистить память и принудительно:

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

Работа с элементами массива

  1. Цикл for
  2. for var i:=0 to High(a) do
       print(a[i]);;
  3. Цикл foreach
  4. foreach var x in a do
        print(x);

High(массив) — возвращает верхнюю границу динамического массива

Пример: поиск элемента в массиве (выдавать индекс искомого)

    Выполнение:
    Выполним сначала БЕЗ использования обобщенной функции:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    function IndexOf(a:array of integer;x:integer):integer;
    begin
      result:=-1;
      for var i:=0 to High(a) do
        if a[i]=x then
        begin
          result:=i;
          break
         end
    end;
    begin
    var a:=Arr(1,2,3,4,5);
    print(IndexOf(a,5))
    end.

    А теперь, выполним с использованием обобщенной функции:

    1
    2
    3
    4
    5
    6
    7
    8
    
    function IndexOf<T>(a:array of T;x:T):integer;
    begin
     ...
    end;
    begin
    var a:=Arr(1,2,3,4,5);
    print(IndexOf(a,5))
    end.

    При вызове обобщенной функции компиляция будет в два этапа:

    1. Автовыведение типа Т, сравнение с реальными цифрами, и т.к. числа целые, то Т определится как integer.
    2. Берется тело функции и заменяется Т на integer (инстанцирование функции с конкретным типом)

    Методы для работы с массивами

  • Reverse(a)
  • var a:=Arr(1,2,3,4,5);
    reverse(a); // [5,4,3,2,1]
  • Sort(a)
  • var a:=Arr(2,3,1,4,5); //[1,2,3,4,5] 
    sort(a);
  • SortByDescending(a); — по убыванию
  • Следующие методы не меняют сам массив:

    a.Min
    a.Max
    a.Sum
    a.Average — среднее арифметическое

  • Cтандартные методы a.IndexOf(x) и a.LastIndexOf(x):
  • begin
      var a := new integer[10];
      a := arrRandomInteger(5,0,5); //[1,3,5,4,5] 
      print(a.IndexOf(3)) // 1
    end.

    или метод a.Contains(x) наравне с x in a:

    begin
      var a := new integer[10];
      a := arrRandomInteger(5,0,5); //[1,3,5,4,5] 
      print(a.Contains(3)); // True
      print(3 in a)// True
    end.

    Некоторые алгоритмы работы с массивами

    Сдвиги

    Пример: дан массив, надо сдвинуть его элементы:
    сдвиги в динамическом массиве

      Стандартное выполнение:

      var a:=Arr(1,2,3,4,5,6);
      var x:=a[0];
      for var i:=0 to 4 do
         a[i]:=a[i+1];
      a[5]:=x;
      print(a)

      Если сдвиг вправо:
      сдвиги в массивах

       // …
        var v := a[0];
        for var i:=0 to a.Length-2 do
          a[i] := a[i+1];
        a[a.Length-1] := v;
      1. либо задействовать еще один массив (𝜭 (n-k) — по времени)
      2. либо много раз запускать один и тот же алгоритм (𝜭 (1) — по памяти)

      Минимальный элемент и его индекс:

      Решение 1:

        // …
        var (min, minind) := (a[0], 0);  
        for var i:=1 to a.Length-1 do
          if a[i]<min then
            (min, minind) := (a[i], i);  Result := (min, minind);

      Решение 2:

        // …
        var (min, minind) := (real.MaxValue, 0);  
        for var i:=0 to a.Length-1 do
          if a[i]<min then
            (min, minind) := (a[i], i);  Result := (min, minind);

      Решение 3:

      begin
        var a := new integer[5];
        a := arrRandomInteger(5); // [86,37,41,45,76] 
        print(a.Min,a.IndexMin); // 37  1
      end.

      Циклический сдвиг влево:

      циклический сдвиг

        // …
        var v := a[0];
        for var i:=0 to a.Length-2 do
          a[i] := a[i+1];
        a[a.Length-1] := v;

      Циклический сдвиг вправо:

        // …
        var v := a[a.Length-1];
        for var i:=a.Length-1 downto 1 do
          a[i] := a[i-1];
        a[0] := v;

      Срезы

      Срез массива — это подмножество исходного массива.

      • Срезы доступны только на чтение, присваивать им значения нельзя.
      • Тип среза такой же, как у массива.
      • Срезы работают с массивами, строками и со списками.
      var a:=Arr(1,2,3,4,5,6);
      print(a[1:5]) // [2,3,4,5]

      a[1:5] — 1-й элемент включая, 5-й не включая

      println(a[:5]); // [1,2,3,4,5] - с начала до 5-го не включая
      println(a[1:]); // [2,3,4,5,6] - до конца
      println(a[::2]); // [1,3,5] - третий параметр - это шаг

      a[::-1] — получим 6 5 4 3 2 1

      срезы в массивах
      Т.о. выполнение при помощи срезов выглядит так:
      Перестановка:

      var a:=Arr(1,2,3,4,5,6);
      var k:=a.Length-1; // 6 - 1
      a:=a[k:]+a[:k];
      print(a) // [6,1,2,3,4,5]

      Т.е. создан еще массив уже со сдвигом.

      Время работы алгоритма n+n, 𝜭 (n)

      Подробнее со срезами можно ознакомиться здесь

      Удаление и вставка элементов массива. Списки

      Для расширения массива путем вставки какого-либо элемента, необходимо предусмотреть место в памяти. По этой причине для данных случаев проще использовать списки:
      Списки — List — это тоже динамический массив, который может «расширяться» и «сужаться» по ходу программы (вставка и удаление элементов).

        
      Подробнее со списками можно ознакомиться здесь

      Решение задач

      Простые задачи

      Пример: Напишите функцию SumArray, возвращающую сумму элементов заданного динамического массива. Выведите длину и сумму элементов массива

      Выполнение:

      1
      2
      3
      4
      5
      6
      7
      8
      
      function SumArray(var a: array of integer): integer:=a.Sum;
      begin
        var a:=new integer[10];
        a:=arrRandomInteger(10);
        foreach var x in a do
          print(x);
        println('длина массива = ',a.Length,' сумма = ',ArraySum(a))
      end.

      Задание 0: Дан массив, вывести его содержимое на экран, разделяя элементы точкой с запятой (процедура PrintArr). Используйте для разделителя delim значение по умолчанию равное ‘;

      Выполнение:
      Дополните код:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
      procedure PrintArr( a: array of integer; delim:string:='; ');
      begin
        foreach var ... in ... do
          print(x,delim);
      end;
      begin
        var a:=new integer[10];
        a:=arrRandomInteger(10);
        ...
      end.

      Пример «Универсальный тип»:
      Написать процедуру для печати значений массива любого типа.

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

      ✍ Решение:

        procedure printArray<T>(a: array of T);
        begin
          for var i:=0 to a.Length-1 do
          begin
            print(a[i]);
          end;
          println
        end;

      Задание 1: Исправить процедуру PrintArr предыдущего задания 0 так, чтобы за последним элементом символ-разделитель не ставился. Реализовать данную процедуру как процедуру универсального типа.

      Задание 2: Заполнить массив (b) первыми N (N ≥ 0) положительными нечётными числами массива a. Необходимо реализовать два различных решения задачи:

      1. Функция MakeOddArrFunc с одним параметром N, возвращающая массив.
      2. Процедура MakeOddArrProc с двумя параметрами: входным — массив a и выходным параметром — массивом положительный нечетных чисел

      1

      Фрагмент программы:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      
      function MakeOddArrFunc (a: array of integer; n:integer):array of integer;
      begin
        var b:= new integer[n];
        var j:=0;
        for var i:=0 to ... do 
          if ... then
            begin ...;...;end;
        SetLength(...,...);
        result:=b;
      end;
      procedure MakeOddArrProc (a: array of integer;var b: array of integer; n:integer);
      begin
       b:= new integer[n];
       var j:=0;
       for var i:=0 to ... do 
          if ... then
            begin ...;...;end;
       SetLength(...,...);
      end;
      begin
        var a:=arrRandomInteger(20);
        var b: array of integer;
        var n:=readInteger('введите N');
        println('исходный массив ',a);
        println('результат работы с функцией ',MakeOddArrFunc(a,n));
        MakeOddArrProc(a,b,n);
       print('результат работы с процедурой ',b) 
      end.

      Задание 3: Заполнить целочисленный массив первыми N (N ≥ 0) числами Фибоначчи. Достаточно одной из реализаций: функции или процедуры

      Фрагмент программы:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
      function MakeFibArr (n : integer):array of integer;
      begin
       var c:= new integer[n];
       c[0]:=...;c[1]:=...;
       for var i:=2 to n-1 do 
          ...;
       result:=c;
      end;
      begin
        var n:= readinteger;
        ...;
      end.

      Задание 4: Дан целочисленный массив. Написать процедуру EvenMult с двумя параметрами: входным (параметр по значению) — целочисленным массивом и выходным (параметр по ссылке) — evensCnt — значением целого типа, которая увеличивает все элементы массива с чётными значениями в два раза и записывает в evensCnt количество таких элементов
      1

      Пример: Описать функцию MakeRandomRealArr с тремя параметрами: целым числом N (N ≥ 0), вещественными параметрами a и b (a < b).
      Функция должна возвращать массив (тип которого либо RealArr либо array of real) из N случайных вещественных элементов в диапазоне a..b.
      Продемонстрируйте заполнение и вывод на экран массива

      Выполнение:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      function MakeRandomRealArr (n : integer;a,b:real):array of real;
      begin
         var c:= ArrRandomReal(n,a,b);
         result:=c;
      end;
      begin
        var n:= readinteger;
        var a:=readReal;
        var b:=readReal;
        println('результат работы с функцией ',MakeRandomRealArr(n,a,b));
      end.

      Задание 5: Дан непустой массив вещественных чисел. Найти его наименьший элемент. Выполнить задание с помощью пользовательской функции FindMin.

      Пример: Дан целочисленный массив. Обнулить все его элементы
      с нечётными индексами (процедура SetToZeroOddIndexes).
      Условный оператор не использовать

      Выполнение:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
      procedure SetToZeroOddIndexes(a: array of integer);
      begin
      var j:=0;
       while j<=a.Length-1 do  begin
          a[j]:=0;j+=2;
       end;
       println('результирующий массив: ',a);
      end;
      begin
        var a:=arrRandomInteger(10);
        println('исходный массив: ',a);
        SetToZeroOddIndexes(a);
      end.

      Задание 6: Дан целочисленный массив, содержащий не менее трёх элементов. Найти значение первого локального минимума. Выполнить задание с помощью пользовательской функции FirstLocMin.

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

      Задание 7: Дан массив целых чисел, содержащий не менее трёх элементов. Найти значение и номер последнего локального максимума. Для этого написать процедуру с двумя выходными параметрами (параметры по ссылке)

      Задачи на срезы

      Задание srez1: Дан массив размера N. Вывести его элементы в обратном порядке

      Пример: Дан массив A размера N и целое число K (1<=K<=N). Вывести его элементы с порядковыми номерами, кратными K:

      Ak, A2*k, A3*k... 

      Условный оператор не использовать.

      Выполнение:

      1
      2
      3
      4
      
      var n:=ReadInteger;
      var a:=ReadArrReal(n);
      var k:=ReadInteger;
      a[k-1 : : k].Print;

      Задание srez2: Дан массив A размера N (N – четное число). Вывести его элементы с четными номерами в порядке возрастания номеров:

      а2, а4, а6, ... аn

      Условный оператор не использовать.

      Задание srez3: Дан массив A размера N (N – нечетное число). Вывести его элементы с нечетными номерами в порядке убывания номеров:

      аn, аn-2, аn-4, ... а1 

      Условный оператор не использовать.

      Пример: Дан массив A размера N. Вывести сначала его элементы с четными номерами (в порядке возрастания номеров), а затем – элементы с нечетными номерами (также в порядке возрастания номеров):

      а2, а4, а6,...а1, а3, а5...

      Условный оператор не использовать

      Выполнение:

      1
      2
      3
      4
      
      var n:=ReadInteger;
      var a:=ReadArrReal(n);
      var srez:=a[1::2]+a[::2];
      Print(srez);

      Задание srez4: Дан массив A размера N. Вывести сначала его элементы с нечетными номерами (в порядке возрастания номеров), а затем – элементы с четными номерами (в порядке убывания номеров):

      а1, а3, а5, ..., а6, а4, а2...

      Условный оператор не использовать

      Пример: Дан массив размера N и целые числа K и L (1<=K<=L<=N). Найти среднее арифметическое элементов массива с номерами от K до L включительно

      Выполнение:

      1
      2
      3
      4
      5
      6
      
      var n:=ReadInteger;
       var a:=ReadArrReal(n);
       var k:=ReadInteger;
       var l:=ReadInteger;
       var srez:=a[k-1:l].Average;
       print(srez);

      Задание srez5: Дан массив размера N и целые числа K и L (1<=K<=L<=N). Найти сумму элементов массива кроме элементов с номерами от K до L включительно

      Пример: Дан массив А размера N. Найти минимальный элемент из его элементов с четными номерами: а2, а4, а6,… .

      Выполнение:

      1
      2
      3
      
      var n:=ReadInteger;
      var a:=ReadArrReal(n);
      print(a[1::2].min);

      Задание srez6: Дан массив. Поменять в нем первую половину со второй (считать, что длина массива – четное число). Порядок элементов в половинах не менять.
      Например:

      [1,2,3,4,5,6,7,8] -> [5,6,7,8,1,2,3,4]

      Использование методов

      Пример: Дан случайный массив. Найти сумму элементов между первым минимальным и последним максимальным. Сделайте 2 версии – с использованием методов и без их использования. Выдайте время работы каждой версии (для достаточно больших массивов) – можно использовать System.DateTime.Now

      Выполнение:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      
      function MyMin(a: array of real): integer;
        begin
        var minInd:=0;
           for var i:=1 to a.Length-1 do begin
            if a[minInd]>a[i] then minInd:=i;
           end;
         result:=minInd;
        end;
        function MyMax(a: array of real): integer;
        begin
        var maxInd:=0;
          for var i:=1 to a.Length-1 do begin
             if a[maxInd]<=a[i] then maxInd:=i;
          end;
         result:=maxInd;
        end;
      begin
      //использование методов
      var n:=readinteger;
      var a:=readArrreal(n);
      var t:=System.DateTime.Now;
      var minInd:=a.IndexMin;
      var maxInd:=a.LastIndexMax;
      var srez1:=a[minind+1:maxind].sum;
      println('Результат 1: ',srez1);
      var t1:=System.DateTime.Now;
      println('Время выполнения: ',t1-t);
      // без использования методов
      t:=System.DateTime.Now;
       minind:= MyMin(a);
       maxind:= MyMax(a);
      srez1:=a[minind+1:maxind].sum;
      println('Результат 2: ',srez1); 
      t1:=System.DateTime.Now;
      println('Время выполнения: ',t1-t);
      end.

      Задание: Даны 2 упорядоченных массива. Создайте третий – их объединение с сохранением упорядоченности (сортировка – метод sort). Как и для предыдущей задачи, сделайте хотя бы 2 варианта работы и сравните их.

      Фрагмент кода:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      
      procedure MySort(c: array of integer);
        begin
      // сортировка методом Пузырька
          for ...
              for ...
                 ...
        end;
      begin
      var a:=arr(1,3,5,6,12);
      var b:=arr(2,6,8,12,16);
      var c:=a+b;
      //использование методов
      var t:=System.DateTime.Now;
      ...
      ...
      var t1:=System.DateTime.Now;
      println('Время выполнения с методом: ',t1-t);
      t:=System.DateTime.Now;
      //без использования методов
      ...
      ...
      ...
      end.

      есть код:

      #include <stdio.h>
      #include <stdlib.h>
      #include <locale.h>
      
      int sumOfOdd(int* array, int n);
      
      int main() {
          setlocale(0, "rus");
          int n;
          printf("введите размер массива: ");
          scanf_s("%d", &n);
          int* array = (int*)malloc(n * sizeof(int)); 
          for (int i = 0; i < n; i++) {
              printf("a[%d] = ", i);
              scanf_s("%d", &array[i]);
          }
          int sum = sumOfOdd(array, n);
          printf("сумма нечетных элементов массива: %d", sum);
          free(array); 
          return 0;
      }
      
      int sumOfOdd(int* array, int n) {
          if (n == 0) {
              return 0; 
          }
          else {
              int sum = sumOfOdd(array, n - 1);
              if (array[n - 1] % 2 != 0) {
                  return sum += array[n - 1]; 
              }
              else {
                  return sum;
              }
          }
      }

      иногда он считает неправильно.
      например: размер массива = 4. элементы: a[0] = 1, a[1] = 2, a[2] = 3, a[3] = 4. программа выводит сумму = 4. хотя должно быть 6 (4+2=6).
      в чем у меня ошибка?

      Добавить комментарий