Си массив указателей: Массивы указателей | Программирование на C и C++

Содержание

1.7.4. Массивы указателей | Электроника для всех

Содержание
На предыдущую страницу к разделу 1.7.3. Операции с указателями

В языке СИ элементы массивов могут иметь любой тип, и, в частности, могут быть указателями на любой тип. Рассмотрим несколько примеров с использованием указателей.
 

Следующие объявления переменных
 

1
2
3
     int a[]={10,11,12,13,14,};
     int *p[]={a, a+1, a+2, a+2, a+3, a+4};
     int **pp=p;

int a[]={10,11,12,13,14,};
int *p[]={a, a+1, a+2, a+2, a+3, a+4};
int **pp=p;

порождают программные объекты, представленные на схеме на рис.4.
 

При выполнении операции pp-p получим нулевое значение, так как ссылки pp и p равны и указывают на начальный элемент массива указателей, связанного с указателем p ( на элемент p[0]).
 

После выполнения операции pp+=2 схема изменится и примет вид, изображенный на рис.5.
 

Результатом выполнения вычитания pp-p будет 2, так как значение pp есть адрес третьего элемента массива p. Ссылка *pp-a тоже дает значение 2, так как обращение *pp есть адрес третьего элемента массива a, а обращение a есть адрес начального элемента массива a. При обращении с помощью ссылки **pp получим 12 — это значение третьего элемента массива a. Ссылка *pp++ даст значение четвертого элемента массива p т.е. адрес четвертого элемента массива a.
 

Если считать, что pp=p, то обращение *++pp это значение первого элемента массива a (т.е. значение 11), операция ++*pp изменит содержимое указателя p[0], таким образом, что он станет равным значению адреса элемента a[1].
 

Сложные обращения раскрываются изнутри. Например обращение *(++(*pp)) можно разбить на следующие действия: *pp дает значение начального элемента массива p[0], далее это значение инкременируется ++(*p) в результате чего указатель p[0] станет равен значению адреса элемента a[1], и последнее действие это выборка значения по полученному адресу, т.е. значение 11.
 

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

1
2
3
4
5
     int a[3][3]={  { 11,12,13 },
                    { 21,22,23 },
                    { 31,32,33 }   };
     int *pa[3]={ a,a[1],a[2] };
     int *p=a[0];

int a[3][3]={ { 11,12,13 },
{ 21,22,23 },
{ 31,32,33 } };
int *pa[3]={ a,a[1],a[2] };
int *p=a[0];

порождают в программе объекты представленные на схеме на рис.6.
 

Рис.6. Схема размещения указателейна двумерный массив.

Согласно этой схеме доступ к элементу a[0][0] получить по указателям a, p, pa при помощи следующих ссылок: a[0][0], *a, **a[0], *p, **pa, *p[0].
 

Рассмотрим теперь пример с использованием строк символов. Объявления переменных
 

1
2
3
     char *c[]={ "abs", "dx", "yes", "no"};
     char **cp[]={ c+3, c+2 , c+1 , c };
     char ***cpp=cp;

char *c[]={ «abs», «dx», «yes», «no»};
char **cp[]={ c+3, c+2 , c+1 , c };
char ***cpp=cp;

можно изобразить схемой представленной на рис.7.
 

Рис.7. Схема размещения указателей на строки.
 

Читать далее. Раздел 1.7.5. Динамическое размещение массивов
Содержание

Массивы и указатели. Урок 12 курса «Основы языка C»

Адресная арифметика

Рассмотрим программу:

#include <stdio.h>
 
#define N 5
 
int main () {
    int arrI[N], i;
 
    for (i=0; i<N; i++)
        printf("%p\n", &arrI[i]);
}

Создается массив arrI, далее в цикле for выводятся значения адресов ячеек памяти каждого элемента массива. Результат выполнения программы будет выглядеть примерно так:

0x7ffffbff4050
0x7ffffbff4054
0x7ffffbff4058
0x7ffffbff405c
0x7ffffbff4060

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

Теперь объявим указатель на целый тип и присвоим ему адрес первого элемента массива:

int *pI;
 
pI = &arrI[0];

Цикл for изменим таким образом:

for (i=0; i<N; i++)
    printf("%p\n", pI + i);

Здесь к значению pI, которое является адресом ячейки памяти, прибавляется сначала 0, затем 1, 2, 3 и 4. Можно было бы предположить, что прибавление к pI единицы в результате дает адрес следующего байта за тем, на который указывает pI. А прибавление двойки вернет адрес байта, через один от исходного. Однако подобное предположение не верно.

Вспомним, что тип указателя сообщает, на сколько байт простирается значение по адресу, на который он указывает. Таким образом, хотя pI указывает только на один байт (первый), но «знает», что его «собственность» простирается на все четыре (или два). Когда мы прибавляем к указателю единицу, то получаем указатель на следующее значение, но никак не на следующий байт. А следующее значение начинается только через 4 байта (в данном случае). Поэтому результат выполнения приведенного цикла с указателем правильно отобразит адреса элементов массива.

Прибавляя к указателям (или вычитая из них) целые значения, мы имеем дело с так называемой адресной арифметикой.

Напишите программу, в которой объявлен массив вещественных чисел из десяти элементов. Присвойте указателю адрес четвертого элемента, затем, используя цикл, выведите на экран адреса 4, 5 и 6-ого элементов массива.

Имя массива — это указатель на адрес его первого элемента

Да, это именно так, данный факт следует принять как аксиому. Вы можете убедиться в этом выполнив такое выражение:

printf("%p = %p\n", arrI, &arrI[0]);

Отсюда следует, что имя массива – это ничто иное, как указатель. (Хотя это немного особенный указатель, о чем будет упомянуто ниже.) Поэтому выражения pI = &arrI[N] и pI = arrI дают одинаковый результат: присваивают указателю pI адрес первого элемента массива.

Раз имя массива — это указатель, ничего не мешает получать адреса элементов вот так:

for (i=0; i<N; i++)
    printf("%p\n", arrI + i);

Соответственно значения элементов массива можно получить так:

for (i=0; i<N; i++)
    printf("%d\n", *(arrI + i));

Примечание. Если массив был объявлен как автоматическая переменная (т.е. не глобальная и не статическая) и при этом не был инициализирован (не присваивались значения), то в нем будет содержаться «мусор» (случайные числа).

Получается, что запись вида arrI[3] является сокращенным (более удобным) вариантом выражения *(arr+3).

Взаимозаменяемость имени массива и указателя

Если имя массива является указателем, то почему бы не использовать обычный указатель в нотации обращения к элементам массива также, как при обращении через имя массива:

int arrI[N], i;
int *pI;
 
pI = arrI;
 
for (i=0; i<N; i++)
    printf("%d\n", pI[i]);

Отсюда следуют выводы. Если arrI — массив, а pI — указатель на его первый элемент, то пары следующих выражений дают один и тот же результат:

  • arrI[i] и pI[i];
  • &arrI[i] и &pI[i];
  • arrI+i и pI+i;
  • *(arrI+i) и *(pI+i).

Что получается в результате выполнения данных пар выражений: адреса или значения элементов массива?

Указателю pI можно присвоить адрес любого из элементов массива. Например, так pI =&arrI[2] или так pI = arr+2. В таком случае результат приведенных выше пар выражений совпадать не будет. Например, когда будет выполняться выражение arrI[i], то будет возвращаться i-ый элемент массива. А вот выражение pI[i] уже вернет не i-ый элемент от начала массива, а i-ый элемент от того, адрес которого был присвоен pI. Например, если pI был присвоен адрес третьего элемента массива (pI = arr+2), то выражение arrI[1] вернет значение второго элемента массива, а pI[1] — четвертого.

Присвойте указателю (pI) ссылку не на первый элемент массива (arrI). В одном и том же цикле выводите результат выражений arrI[i] и pI[i], где на каждой итерации цикла i для обоих выражений имеет одинаковое значение. Объясните результат выполнения такой программы.

Имя массива — это указатель-константа

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

Это значит, что выражение pI = arrI допустимо, а arrI = pI нет. Имя массива является константой. При этом не надо путать имя массива (адрес) и значения элементов массива. Последние константами не являются. Действительно, ведь для всех переменных мы не можем менять их адрес в процессе выполнения программы, можем менять лишь их значения. В этом смысле имя массива — это обычная переменная, хотя и содержащая адрес.

Как следствие в программном коде выражения присваивания, инкрементирования и декрементирования допустимы для указателей, а для имени массива — запрещены.

Посмотрите на программу ниже. Что она делает? Почему? Проверьте ваши рассуждения опытным путем.

#include <stdio.h>
 
int main () {
    char str[20], *ps = str, n=0;
 
    printf("Enter word: ");
    scanf("%s", str);
 
    while(*ps++ != '\0') n++;
 
    printf("%d\n", n);
}

Курс с решением части задач:
android-приложение, pdf-версия

programming is an art: Массивы в Си (Массив указателей и 3D-массив)

В этом уроке я расскажу вам о двух темах: массиве указателей и трехмерных массивах. Итак, не теряя времени, давайте перейдем к первой теме этого урока.

Массив указателей в C

Как я уже говорил, «Массив — это набор элементов схожих типов данных». Мы уже создали массив целых чисел, чисел с плавающей точкой и так далее. Итак, один вопрос, который возникает. Можем ли мы сделать массив указателей? Ну, ответ, конечно, да. Чтобы создать массив, мы должны выполнить только одно условие, то есть он должен содержать элементы одного типа данных. Таким образом, мы можем хранить указатели изолированных переменных внутри массива. Давайте возьмем один пример, чтобы понять это.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

#include<stdio.h>

 

int main()

{

int *a[4]; //declaration of array of pointers

int x=23,y=54,z=65,p=45,q;

 

a[0]=&x;

a[1]=&y;

a[2]=&z;

a[3]=&p;

 

for(q=0;q<4;q++)

  printf(«%d «,*a[q]);

 

return 0;

}

Выход 
23 54 65 45 

объяснение

  • В начале программы я объявил одномерный массив указателей размером 4. Это означает, что он может хранить адреса четырех изолированных переменных-указателей.
  • После этого я объявил некоторые целочисленные переменные и сохранил в нем некоторые значения.
  • Теперь я сохранил адреса целочисленных переменных внутри массива указателей a.
  • В последнем я напечатал все значения по адресам, хранящимся в этом массиве, используя цикл for.

Примечание. Мы можем даже хранить адреса других массивов внутри массива указателей.

3D-массив в C

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

Объявление и инициализация 3D-массива

Давайте возьмем один пример, чтобы понять это.

int a [2] [2] [2] = { 

{13, 56}, 
{54, 67} 
}, 

{64, 87}, 
{23, 678} 

};

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

Выделение памяти в 3D-массиве

Распределение памяти трехмерного массива аналогично двумерному массиву . Поскольку элементы внутри 3D-массива всегда хранятся в смежных местах памяти.

НОУ ИНТУИТ | Лекция | Основы языка Си: структура Си-программы, базовые типы и конструирование новых типов, операции и выражения

Аннотация: Лекция посвящена введению в язык Си. Объясняются общие принципы построения Си-программы: разбиение проекта на h- и c-файлы, т.е. разделение интерфейса и реализации, использование препроцессора. Приводятся базовые типы языка Си, конструкции массива и указателя, позволяющие строить новые типы, а также модификаторы типов. Рассматриваются всевозможные операции и выражения языка Си.

Основы языка Си

В настоящее время язык Си и объектно-ориентированные языки
его группы (прежде всего C++, а также Java и C#) являются основными
в практическом программировании. Достоинство языка Си — это,
прежде всего, его простота и лаконичность. Язык Си легко учится.
Главные понятия языка Си, такие, как статические и локальные
переменные, массивы, указатели, функции и т.д., максимально приближены
к архитектуре реальных компьютеров. Так, указатель — это просто адрес
памяти, массив — непрерывная область памяти, локальные переменные — это
переменные, расположенные в аппаратном стеке,
статические — в статической памяти. Программист,
пишущий на Си, всегда достаточно точно представляет себе, как
созданная им программа будет работать на любой конкретной архитектуре.
Другими словами, язык Си предоставляет программисту
полный контроль над компьютером.

Первоначально язык Си задумывался как заменитель Ассемблера
для написания операционных систем. Поскольку Си — это язык
высокого уровня, не зависящий от конкретной архитектуры, текст
операционной системы оказывался легко переносимым с одной платформы на
другую. Первой операционной системой, написанной практически целиком на
Си, была система Unix. В настоящее время почти все используемые операционные системы написаны на Си. Кроме того, средства программирования, которые операционная система
предоставляет разработчикам прикладных программ (так называемый API —
Application Program Interface), — это наборы системных функций на языке Си.

Тем не менее, область применения языка Си не ограничилась
разработкой операционных систем. Язык Си оказался очень удобен
в программах обработки текстов и изображений, в научных и инженерных расчетах.
Объектно-ориентированные языки на основе Си
отлично подходят для программирования в оконных средах.

В данном разделе будут приведены лишь основные понятия языка
Си (и частично C++). Это не заменяет чтения полного учебника по
Си или C++, например, книг [6] и [8].

Мы будем использовать компилятор C++ вместо Cи. Дело в том,
что язык Си почти целиком входит в C++, т.е. нормальная программа,
написанная на Си, является корректной C++ программой. Слово
«нормальная» означает, что она не содержит неудачных конструкций,
оставшихся от ранних версий Си и не используемых в настоящее
время. Компилятор C++ предпочтительнее, чем компилятор Си, т.к.
он имеет более строгий контроль ошибок. Кроме того, некоторые
конструкции C++, не связанные с объектно-ориентированным программированием,
очень удобны и фактически являются улучшением
языка Си. Это, прежде всего, комментарии //, возможность описывать
локальные переменные в любой точке программы, а не только в начале блока,
и также задание констант без использования оператора #define препроцесора.
Мы будем использовать эти возможности
C++, оставаясь по существу в рамках языка Си.

Структура Си-программы

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

В языке Си исходные файлы бывают двух типов:

  • заголовочные, или h-файлы;
  • файлы реализации, или Cи-файлы.

Имена заголовочных файлов имеют расширение » .h «. Имена файлов реализации имеют расширения » .c » для языка Си и » .cpp «, » .cxx » или » .cc » для языка C++.

К сожалению, в отличие от языка Си, программисты не сумели договориться о едином расширении имен для файлов, содержащих программы на C++. Мы будем использовать расширение » .h » для заголовочных файлов и расширение » .cpp » для файлов реализации.

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

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

означающее, что переменная x определена где-то в файле реализации (в каком — неизвестно). Слово extern (внешняя) лишь сообщает информацию о внешней переменной, но не определяет эту переменную.

Файлы реализации, или Cи-файлы, содержат тексты функций и определения глобальных переменных. Говоря упрощенно, Си-файлы содержат сами программы, а h-файлы — лишь информацию о программах.

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

Файлы реализации могут подключать описания, содержащиеся в заголовочных файлах. Сами заголовочные файлы также могут использовать другие заголовочные файлы. Заголовочный файл подключается с помощью директивы препроцессора #include. Например, описания стандартных функций ввода-вывода включаются с помощью строки

(stdio — от слов standard input/output). Имя h-файла записывается в угловых скобках, если этот h-файл является частью стандартной Си-библиотеки и расположен в одном из системных каталогов. Имена h-файлов, созданных самим программистом в рамках разрабатываемого проекта и расположенных в текущем каталоге, указываются в двойных кавычках, например,

Препроцессор — это программа предварительной обработки текста
непосредственно перед трансляцией. Команды препроцессора называются директивами. Директивы препроцессора содержат символ диез # в начале
строки. Препроцессор используется в основном для подключения h-файлов.
В Си также очень часто используется директива #define для задания
символических имен констант. Так, строка

задает символическое имя PI для константы 3.14159265. После этого
имя PI можно использовать вместо числового значения. Препроцессор
находит все вхождения слова PI в текст и заменяет их на константу.
Таким образом, препроцессор осуществляет подмену одного текста другим.
Необходимость использования препроцессора всегда свидетельствует о
недостаточной выразительности языка. Так, в любом Ассемблере средства
препроцессирования используются довольно интенсивно. В Си по возможности
следует избегать чрезмерного увлечения командами препроцессора — это
затрудняет понимание текста программы и зачастую ведет к трудно
исправляемым ошибкам. В C++ можно обойтись без использования директив #define для задания констант. Например, в C++ константу PI можно задать
с помощью нормального описания

const double PI = 3.14159265;

Это является одним из аргументов в пользу применения компилятора
C++ вместо Си даже при трансляции программ, не содержащих конструкции
класса.

как передать массив указателей на процедуру в большой сборке модели?

У меня есть код C, который определяет функцию, функция реализована в ASM в большой памяти модели.
процедура получает массив указателей (матрицу), два целых числа и 4 указателя. внутри функции я вызываю другую процедуру, которая получает два массива, два указателя и одно целое число.
теперь, как я понимаю, при инициировании вызова параметры передаются через стек, а в большой модели, когда передается указатель, передаются смещение и сегмент этого указателя.мой вопрос: как передать 2 массива из массива указателя (т.е. два указателя) в другую процедуру? У меня нет проблем с передачей целого числа и двух указателей другой процедуре (я нажимаю смещение и сегмент указателей, а затем нажимаю значение целого числа)

вот мой код ASM:

  общедоступная _find_closest_matrix_pair
_find_closest_matrix_pair proc far
толкнуть бп
mov bp, sp
толкни си
толкни ди
нажимай es

mov ax, [bp + 10]
mov n, ax
mov ax, [bp + 12]
mov m, ax

mov es, [bp + 28]
mov bx, [bp + 26]
нажимай es
толкнуть bx
mov es, [bp + 20]
mov bx, [bp + 18]
нажимай es
толкнуть bx

mov ax, m
толкать топор

mov si, [bp + 6]
mov es, [bp + 8]
mov di, si
добавить ди, 2

нажимай es
нажать слово ptr [di]
нажимай es
нажать слово ptr [si]

Позвоните в find_closest_pair

добавить sp, 18
; получить возвращаемое значение:
mov min1,0
добавить слово ptr min1, ax
adc word ptr min1 + 2, dx
; обновить индексы:
mov es, [bp + 20]
mov bx, [bp + 18]
mov ax, es: [bx]
mov j_min1, топор
mov es, [bp + 28]
mov bx, [bp + 26]
mov ax, es: [bx]
mov j_min2, топор
mov cx, 0
mov es, [bp + 16]
mov bx, [bp + 14]
mov es: [bx], cx
mov ax, es: [bx]
mov i_min1, топор
inc cx
mov es, [bp + 24]
mov bx, [bp + 22]
mov es: [bx], cx
mov ax, es: [bx]
mov i_min2, топор

mov si, [bp + 6]

mov s, 0
loop1:
mov di, si
добавить ди, 2

mov bx, s
inc bx
mov k, bx
loop2:

mov es, [bp + 28]
mov bx, [bp + 26]
нажимай es
толкнуть bx
mov es, [bp + 20]
mov bx, [bp + 18]
нажимай es
толкнуть bx

mov ax, m
толкать топор

mov es, [bp + 8]

нажимай es
нажать слово ptr [di]
нажимай es
нажать слово ptr [si]

позвонить find_closest_pair

добавить sp, 18
; получить возвращаемое значение:
mov temp, 0
добавить слово ptr temp, ax
adc word ptr temp + 2, dx

mov ecx, temp
cmp ecx, min1
jae continue1
mov min1, ecx

; обновить индексы:
mov es, [bp + 20]
mov bx, [bp + 18]
mov ax, es: [bx]
mov j_min1, топор
mov es, [bp + 28]
mov bx, [bp + 26]
mov ax, es: [bx]
mov j_min2, топор
mov ax, s
mov es, [bp + 16]
mov bx, [bp + 14]
mov es: [bx], ax
mov i_min1, топор
mov ax, k
mov es, [bp + 24]
mov bx, [bp + 22]
mov es: [bx], ax
mov i_min2, топор

continue1:
добавить ди, 2
inc k
mov cx, n
cmp k, cx
jb loop2
добавить си, 2
inc s
mov cx, n
cmp s, cx
jb loop1

mov ax, 0
mov dx, 0
добавить топор, слово ptr min1
adc dx, слово ptr min1 + 2

mov cx, i_min1
mov es, [bp + 16]
mov bx, [bp + 14]
mov es: [bx], cx

mov cx, j_min1
mov es, [bp + 20]
mov bx, [bp + 18]
mov es: [bx], cx

mov cx, i_min2
mov es, [bp + 24]
mov bx, [bp + 22]
mov es: [bx], cx

mov cx, j_min2
mov es, [bp + 28]
mov bx, [bp + 26]
mov es: [bx], cx

поп-эс
поп ди
поп си
pop bp
Ret
_find_closest_matrix_pair endp
  

Примечание

: find_closest_pair — другая процедура, упомянутая выше.заранее спасибо.

Шпаргалка по сложности алгоритма

Big-O (Знай свои сложности!) @Ericdrowell

Всем привет! Эта веб-страница охватывает пространственные и временные сложности Big-O распространенных алгоритмов, используемых в компьютерных науках. В прошлом, когда я готовился к техническим собеседованиям, я обнаружил, что часами ползаю по Интернету, собирая воедино лучшие, средние и наихудшие сложности для алгоритмов поиска и сортировки, чтобы меня не озадачили, когда меня спросят о них.За последние несколько лет я брал интервью у нескольких стартапов Кремниевой долины, а также у некоторых крупных компаний, таких как Google, Facebook, Yahoo, LinkedIn и Uber, и каждый раз, когда я готовился к интервью, я думал про себя: «Почему? разве кто-нибудь не создал хорошую шпаргалку по Big-O? ». Итак, чтобы сэкономить вам кучу времени, я пошел дальше и создал его. Наслаждаться! — Эрик

Ознакомьтесь с El Grapho, библиотекой визуализации данных графа, которая поддерживает миллионы узлов и ребер. n) O (n!) Операции Элементы

Операции со структурой общих данных

Структура данных Сложность времени Космическая сложность
Среднее значение Худшее Худшее
Доступ Искать Вставка Удаление Доступ Искать Вставка Удаление
Массив Θ (1) Θ (н) Θ (н) Θ (н) О (1) О (н) О (н) О (н) О (н)
Стек Θ (н) Θ (н) Θ (1) Θ (1) О (н) О (н) О (1) О (1) О (н)
Очередь Θ (н) Θ (н) Θ (1) Θ (1) О (н) О (н) О (1) О (1) О (н)
Односвязный список Θ (н) Θ (н) Θ (1) Θ (1) О (н) О (н) О (1) О (1) О (н)
Двусвязный список Θ (н) Θ (н) Θ (1) Θ (1) О (н) О (н) О (1) О (1) О (н)
Пропустить список Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) О (н) О (н) О (н) О (н) O (n log (n))
Хеш-таблица НЕТ Θ (1) Θ (1) Θ (1) НЕТ О (н) О (н) О (н) О (н)
Дерево двоичного поиска Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) О (н) О (н) О (н) О (н) О (н)
Декартово дерево НЕТ Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) НЕТ О (н) О (н) О (н) О (н)
B-дерево Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) O (лог (n)) O (лог (n)) O (лог (n)) O (лог (n)) О (н)
Красно-черное дерево Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) O (лог (n)) O (лог (n)) O (лог (n)) O (лог (n)) О (н)
Простое дерево НЕТ Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) НЕТ O (лог (n)) O (лог (n)) O (лог (n)) О (н)
AVL Дерево Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) O (лог (n)) O (лог (n)) O (лог (n)) O (лог (n)) О (н)
KD Дерево Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) Θ (лог (п)) О (н) О (н) О (н) О (н) О (н)

Алгоритмы сортировки массивов

Узнать больше

Получить официальный плакат с шпаргалкой по Big-O

Авторы

  1. Эрик Роуэлл
  2. Квентин Плепл
  3. Майкл Эбед
  4. Ник Дизаззо
  5. Адам Форсайт
  6. Феликс Чжу
  7. Джей Инженер
  8. Джош Дэвис
  9. Нодир Туракулов
  10. Дженнифер Хамон
  11. Дэвид Дорфман
  12. Барт Мэсси
  13. Луч Переда
  14. Si Pham
  15. Майк Дэвис
  16. Макверри
  17. Макс Хоффманн
  18. Бахадор Сакет
  19. Дэймон Дэвисон
  20. Элвин Ван
  21. Алан Бриолат
  22. Дрю Хэнней
  23. Эндрю Расмуссен
  24. Деннис Цанг
  25. Винни Магро
  26. Адам Арольд
  27. Алехандро Рамирес
  28. Анил Назарет
  29. Рахул Чоудхури
  30. Джонатан МакЭлрой
  31. Стивен41292
  32. Брэндон Амос
  33. Джоэл Фридли
  34. Каспер Ван Гелуве
  35. Эрик Лефевр-Ардан
  36. Олег
  37. Ренфред Харпер
  38. Пайпер Честер
  39. Мигель Амигот
  40. Апурва К
  41. Мэтью Даронко
  42. Юнь-Ченг Линь
  43. Клэй Тайлер
  44. Орхан Джан Озалп
  45. Айман Сингх
  46. Дэвид Мортон
  47. Аурелиен Оомс
  48. Себастьян Паске Торхольм
  49. Кушик Кришнан
  50. Дрю Бейли
  51. Роберт Берк

Сделайте эту страницу лучше

Отредактируйте эти таблицы!

Размер шрифта — Попутный ветер CSS

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

Управляйте размером шрифта элемента с помощью утилит text- {size} .

Адаптивный

Чтобы управлять размером шрифта элемента в определенной точке останова, добавьте префикс {screen}: к любой существующей утилите размера шрифта. Например, используйте md: text-lg , чтобы применить утилиту text-lg только для средних размеров экрана и выше.

  

Быстрая коричневая лиса перепрыгнула через ленивую собаку.

Дополнительную информацию о функциях адаптивного дизайна Tailwind можно найти в документации по адаптивному дизайну.

Настройка

Размер шрифта

По умолчанию Tailwind предоставляет 10 утилит с размером шрифта . Вы изменяете, добавляете или удаляете их, редактируя раздел theme.fontSize вашей конфигурации Tailwind.

 
  module.exports = {
    тема: {
      размер шрифта: {
- 'xs': '.75rem',
- 'sm': '.875rem',
+ 'крошечный': '.875rem',
        'база': '1рем',
        'lg': '1,125 rem',
        'xl': '1,25рем',
        '2xl': '1.5rem',
- '3xl': '1.875ремь,
- '4xl': '2.25rem',
        '5xl': '3rem',
        '6xl': '4rem',
+ '7xl': '5rem',
      }
    }
  }  

Предоставление высоты строки по умолчанию

Вы можете указать высоту строки по умолчанию для каждого размера шрифта, используя кортеж формы [fontSize, lineHeight] в файле tailwind.config.js .

 
module.exports = {
  тема: {
    размер шрифта: {
      sm: ['14px', '20px'],
      база: ['16px', '24px'],
      lg: ['20px', '28px'],
      xl: ['24px', '32px'],
    }
  }
}  

Мы уже предоставляем высоту строки по умолчанию для каждого .текст- {size} класс.

Предоставление межбуквенного интервала по умолчанию

Если вы также хотите указать значение межбуквенного интервала по умолчанию для размера шрифта, вы можете сделать это, используя кортеж вида [fontSize, {letterSpacing, lineHeight}] в вашем tailwind.config.js файл.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *