
- •Какую ide(Среду разработки) выбрать?
- •3) Символьная переменная — char.
- •4) Логическая переменная — bool
- •1) Вывод
- •1) Ввод
- •1)Стандартные математические операции,
- •2)Бинарные операции,
- •2) Бинарные операции, продолжение
- •1) Sqrt(a)
- •3) Fmod(a,b)
- •2) While
- •2) Создание функции.
- •3) Функция для перевода из 10-ой системы счисления в k-ую.
- •Поделиться в соц. Сетях
- •Имя файла:
- •Поделиться в соц. Сетях Структуры данных. Стек
- •1) Сокращение выражений:
- •2) Инкремент, декремент
- •3) Считывание переменных в цикле
- •Поделиться в соц. Сетях
Поделиться в соц. Сетях Структуры данных. Стек
Опубликовано 16.05.2013 автором Dauren
Что такое структура данных?
Это способ хранения данных по особым правилам, использующий функции для доступа к ним. Одним из структур данных является стек (англ. stack - стопка).
Стек немного схож с ханойской башней. Вкратце вся суть этой игры такова:
Имеется доска с тремя стержнями;
На первом находятся восемь колец упорядоченных по размеру, т.е. получается своеобразная пирамида;
Нужно перенести кольца с первого стержня на третий, притом кольцо может лежать лишь на доске или же на кольце большего размера.
Теперь более формально.
Стек это — структура данных, использующая следующие функции:
push (x): добавить элемент x на самый верх стека;
top (): возвратить значение самого верхнего элемента;
pop (): удалить самый верхний элемент;
Получается некий шампур (т.е. стек), на который мы нанизываем еду (т.е информацию).
Cтек уже реализован в С++, в качестве контейнера. Перечислим все его функции:
stack < a > b - создать стек типа b с именем a;
b.push (x) — добавить в стек b элемент x (x должен быть того же типа, что и сам стек);
b.pop () - удалить самый верхний элемент стека;
b.top () — возвратить значение самого верхнего элемента стека;
b.size () - возвратить количество элементов в стеке;
b.empty () - true, если стек пуст, иначе — false;
Пример работы со стеком:
1 2 3 4 5 6 7 8 9 10 11 |
stack < int > st; // создание стека типа integer в c++ st.push (1); // [1] st.push (2); // [1][2] st.push (3); // [1][2][3] cout << st.top () << "\n"; // [1][2]->[3]<-, выводим "3" st.push (4); // [1][2][3][4] cout << st.top () << "\n"; // [1][2][3]->[4]<-, выводим "4" st.pop (); // [1][2][3] st.pop (); // [1][2] st.pop (); // [1] cout << st.top () << "\n"; // ->[1]<-, выводим "1" |
Но ведь так не интересно, давайте напишем свой стек, хотя бы просто для int-ов. Сразу выкладываю код, объяснения как обычно там же:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# include <iostream> # include <cstdlib> # include <cstdio>
using namespace std;
int st[1000]; // наш будущий стек int st_size; // размер стека, изначально положим равным нулю
void push (int x) { st[++st_size] = x; // увеличиваем размер стека и сразу записываем в него наш элемент }
void pop () { st[st_size--] = 0; // обнуляем верхний элемент и уменьшаем размер стека }
int top () { return st[st_size]; // возвращаем значение самого верхнего элемента }
int size () { return st_size; // возвращаем размер стека }
bool empty () { if (st_size >= 1) // проверяем, есть ли в стеке хоть 1 элемент return true;
return false; // иначе возвращаем false }
int main () { push (1); // [1] push (2); // [1][2] push (3); // [1][2][3]
cout << top () << "\n"; // [1][2]->[3]<-, выводим "3"
push (4); // [1][2][3][4]
cout << top () << "\n"; // [1][2][3]->[4]<-, выводим "4"
pop (); // [1][2][3] pop (); // [1][2] pop (); // [1]
cout << top () << "\n"; // ->[1]<-, выводим "1"
system ("pause");
return 0; } |
Теперь, разобравшись с теорией, поговорим об использовании стека.
Вы когда-нибудь слышали о обратной польской нотации (далее ОПН)? Если да, то наверняка слышали и остековой машине, используемой для решения ОПН.
В простых словах, ОПН это — вид записи арифметических выражений, не использующий скобок для указания порядка действий. Вместо скобок, для указания порядка действий, используется стек. Также в нем знаки стоят после самих чисел (т.е «2 + 2″ в простой записи это — «2 2 +» в ОПН).
Для полного понимания пример:
X3 * (2xy — 36) тоже самое, что и X X X * * 2 X Y * * 36 — *
Любой число (в нашем случае X или Y) значит добавление в стек этого числа
Любой знак (арифметический или бинарный, о которых подробнее писалось тут) значит произвести операцию, связанную с этим знаком, над двумя верхними числами в стеке, и заменить эти два числа результатом. Для лучшего понимания разбор нашего примера (X X X * * 2 X Y * * 36 — *):
[стек до операции] -> [после]
1) [] -> [X]
2) [X] -> [X,X]
3) [X,X] -> [X,X,X]
4) [X,X,X] -> [X,X2]
5) [X,X2] -> [X3]
6) [X3] -> [X3,2]
7) [X3,2] -> [X3,2,X]
8) [X3,2,X] -> [X3,2,X,Y]
9) [X3,2,X,Y] -> [X3,2,XY]
10) [X3,2,XY] -> [X3,2XY]
11) [X3,2XY] -> [X3,2XY,36]
12) [X3,2XY,36] -> [X3,2XY-36]
13) [X3,2XY-36] -> [X3*(2XY-36)]
В качестве закрепления темы, советую написать стековую машину реализующую решение ОПН. Спасибо за внимание, удачи в начинаниях.
Z-функция строки. Число вхождений подстроки в строку.
Опубликовано 31.01.2013 автором admin
Доброго времени суток всем Тема сегодняшней статьи будет о том, как найти число вхождений подстроки в строку. Ну, а в частности, делать мы это будем с помощью нахождения z-функции строки.
Конечно существует очень много алгоритмов, которые могут помочь нам в этом, но сегодня мы рассмотрим именно этот.
Итак, для начала определимся что такое z-функция.
Допустим, мы имеет строку s и массив z. В каждой i-той ячейке массива мы будем хранить максимальное количество символов (число), которые полностью совпадают с символами находящимися вначале строки. Для более понятного объяснения, вот Вам наглядное пособие).
ОБЪЯСНЕНИЕ
Как Вы видите, здесь мы имеем строку abacaba. Теперь разберем массив. В первой ячейке мы пишем 0, потому что для нее не нужно находить какое-либо значение, так как мы уже знаем что оно будет максимально.
Далее, мы имеем символ ‘b’, который не совпадает даже с первой буквой строки, и поэтому пишем ’0′. Третьей буквой (соответственно в массиве 2 индекс), мы видим букву ‘a’, и так как она совпадает с первой буквой строки увеличиваем значение на 1. Дальше идет ‘c’, и в 3 ячейке массива мы пишем ноль.
Следующая буква снова ‘a’, и мы увеличиваем значение на 1. Сразу за ней мы видим ‘b’, и соответственно УЖЕ ДВА СИМВОЛА совпадают с начальными двумя. Увеличиваем 4 ячейку еще на 1. За ней идет снова ‘a’, и мы снова видим что она совпадает со следующей буквой. Также увеличиваем на 1. Вообщем выходит 3. И так далее.
КОД АЛГОРИТМА
Теперь рассмотрим саму функцию, реализованную на С++, которая работает за асимптотику О(n*n), то есть квадрат от длины строки.
Это очень простой код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# include <iostream>
using namespace std;
int zf[100];
int main() { string s; cin>>s;
for(int i=1; i<s.size(); ++i) { while(s[zf[i]]==s[zf[i]+i]) zf[i]++; }
for(int i=0; i<s.size(); ++i) cout<<zf[i];
system("pause"); } |
Здесь мы для каждой ячейки сравниваем символы и увеличиваем ответ для zf[i], пока не найдем НЕсовпадение или не дойдем до конца строки.
Этот алгоритм работает не так быстро, так что теперь рассмотрим наиболее быстрый метод решения этой задачи.
КОД ЭФФЕКТИВНОГО НАХОЖДЕНИЯ Z-ФУНКЦИИ
В этом алгоритме, мы будем максимально использовать информацию, которую уже нашли до того, как дошли до i-той ячейки.
Этот код уже немного побольше, но все заключается в том, что если мы ищем ответ для какой-то подстроки, которая меньше той, для которой мы искали ответ раньше, мы можем воспользоваться информацией, которую получили заранее.
Вот сам код:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# include <iostream>
using namespace std;
int zf[100];
int main() { string s; cin>>s;
//Здесь мы будем хранить //координаты самого длинного //отрезка, который совпадает с //началом нашей строки int r=-1,l=-1;
//Запускаем цикл для прохождения по строке for(int i=1; i<s.size(); ++i) { //Проверяем, если ячейка для //которой мы ищем ответ //находится в отрезке между //l и r if(i<=r) { /* Это означает, что у нас уже есть такая же ячейка для которой мы искали ответ */ zf[i]=min(r-i+1,zf[i-l]); } //Теперь пользуемся тривиальным алгоритмом while(s[zf[i]]==s[zf[i]+i]) zf[i]++; //И обновляем границы нашей подстроки if(i+z[i]-1>r) { l=i; r=i+z[i]-1; } }
//Выводим ответ на экран for(int i=0; i<s.size(); ++i) cout<<zf[i];
system("pause"); } |
Ну что ж, теперь подумаем, как можно использовать алгоритм нахождения z-функции для нахождения количества вхождения подстроки?
Для этого, нам стоит просто поместить подстроку которую мы ищем вперед, и разделить ее каким-либо знаком. Знаю что не понятно ;))) поэтому покажу как)))
Допустим, есть строка abcqweabcqwe и нам нужно найти в ней строку abc.
Для этого соединим все в одну строчку вот так: abc#abcqweabcqwe
Теперь мы можем просто запустить z-функцию, и она найдет нам такой ответ:
Как вы видите, здесь она нашла все вхождения строк, которые совпадают с началом строки (до символа #). Значит остается только пройти по массиву, и посчитать сколько раз у нас встречается цифра которая равна длине нашей строки.
Ну в общем, в конце у меня вышел такой код: (может кому пригодится )
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 37 38 39 40 41 |
# include <iostream>
using namespace std;
int zf[100];
int main() { string h,f; cin>>h>>f; string s=f+"#"+h;
int r=-1,l=-1;
for(int i=1; i<s.size(); ++i) {
if(i<=r) {
zf[i]=min(r-i+1,zf[i-l]); }
while(s[zf[i]]==s[zf[i]+i]) zf[i]++;
if(i+zf[i]-1>r) { l=i; r=i+zf[i]-1; } }
cout<<s<<endl;
for(int i=0; i<s.size(); ++i) cout<<zf[i];
cout<<endl; system("pause"); } |
Спасибо за внимание, скоро напишу еще что-нибудь из алгоритмов на С++. Кстати, кому что надо, ну там какие статьи или информация пишите в комменты, как прочту так напишу статейку.
Быстрое возведение числа в степень на С++
Опубликовано 29.01.2013 автором admin
Всем привет! Очередная статья по алгоритмам языка С++, и сегодня мы будем учиться писать функцию, которая возводит число в степень за log(степень).
Если вы еще не читали что такое функция на С++ или как писать программы на С++, то советуем Вам посетить эти статьи(ну по возможности и прочитать )
Функции в С++
Что такое С++
Итак, начнем нашу лекцию). Для начала хочу рассказать о простых математических формулах, который будут использованы в нашей функции для быстрого возведения числа в степень.
Как Вы знаете, если у нас есть число A в степени X, то есть AX, мы можем написать это как (Az)y, где z*y=x.
Соответственно, если z будет просто 2, нам потребуется лишь возвести число в квадрат, а y поделить на 2.
Но также стоит учитывать такой случай, когда Х может быть нечетным числом. Тогда нам нужно просто возвести А в квадрат, и после чего продолжать наши действия деления X (Так как С++ при делении int`a будет оставлять только целую часть).
Теперь когда принцип работы алгоритма нам известен, осталось показать Вам код и все встанет на свои места
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 |
# include <iostream>
using namespace std;
int bin_pow(int a, int b) { int res = 1; while(b) { if(b % 2 == 1) { res *=a; } b/=2; a*=a; } return res; }
int main() { int a,b; cout<<bin_pow(a,b);
system("pause"); } |
Теперь немного разберем код. У нас есть функция под названием bin_pow, которая принимает два параметра, переменные А и B.
После этого, мы проверяем условие того, что B нечетное, и если оно выполнено, возводим ответ в квадрат.
Теперь просто продолжаем наши действия с делением степени и возведением числа А в квадрат.
После того, как B, становится единицей, мы останавливаем цикл и возвращаем ответ.
Надеюсь, алгоритм работы был понятен, спасибо за внимание!
Изменение позиции курсора. С++
Опубликовано 05.12.2012 автором admin
Всем привет! С вами я, Руслан, администратор сообщества. Сегодня хотел рассказать вам о том, как когда-то писал маленькие «программы-приколы» на с++.
Итак, речь пойдет о так сказать бешеном курсоре, а именно о изменении позиции курсора на с++. Для начала хочу сказать, что для того чтобы переместить курсор на с++ нам потребуется библиотека windows.h, которая есть во всех современных компиляторах. Писать мы будем на Dev C++. Ее можно скачать с официального сайта или прямо у нас. Вот тут —> Скачать Bloodshed Dev C++.
Теперь когда вы установили себе эту прекраснейшую программу перейдем непосредственно к делу. Будем писать (ну может кто-то копировать) код
Сразу скажу, что код программы совсем небольшой, а вот и он:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include<iostream> #include<windows.h> using namespace std; int main() { int x; int y; for(int i=0; i<10; ++i) { x=600+rand()%800; y=600+rand()%800; SetCursorPos(x,y); cout<<"\a"; Sleep(600); } } |
Теперь объяснения. Сначала подключаем необходимые библиотеки, а именно iostream и windows.h. После чего создаем две переменные, которые будут отвечать за положение курсора на экране (то есть его координаты). Ну а потом самое интересное
Пускаем цикл до 10 (но если вы хотите реально напугать юзера, то можно и бесконечный) и каждую итерацию присваиваем переменным координат рандомные значение от 600 до 800 (примерно посередине экрана) и теперь внимание, используем функцию SetCursorPos, для смены позиции курсора на экране.
Регистр букв (большие и маленькие) писать точно такой как тут. Иначе функция не будет работать.
Дальше еще немного пугаем юзера и делаем команду
1 |
cout<<"\a"; |
которая будет заставлять процессор (точнее материнскую плату) пикать
Ну и в конце ставим небольшую паузу на полсекунды, чтобы пользователь (жертва) смог заметить куда делся курсор. И так цикл повторяет 10 раз).
Вот, на сегодня все, думаю вам понравится)
C++. Математические операции. Считывание данных.
Опубликовано 01.12.2012 автором admin
Здравствуйте! Скопилось много не рассказанной информации, но все же ее недостаточно для отдельного урока. Поэтому решил выделить ее просто в отдельный пост.
Предыдущие уроки вы можете найти на этой странице.