[C++] Vector

choohaยท2026๋…„ 1์›” 17์ผ

C++

๋ชฉ๋ก ๋ณด๊ธฐ
19/22

๐Ÿ“š C++ Vector

๐Ÿ”ธ Vector๋ž€?

Vector์˜ ํŠน์ง•

  • ๋™์  ํฌ๊ธฐ ๋ฐฐ์—ด (Dynamic Size Array)
  • ์‹œํ€€์Šค ์ปจํ…Œ์ด๋„ˆ (Sequence Container)
  • ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ์›์†Œ ์ €์žฅ
  • C++์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ

Vector ๊ฐ์ฒด์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ

Vector ๊ฐ์ฒด (์Šคํƒ):
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ ํฌ์ธํ„ฐ (8 bytes)    โ”‚ โ†’ ์‹ค์ œ ๋ฐ์ดํ„ฐ (ํž™)
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ size (8 bytes)     โ”‚   ํ˜„์žฌ ์›์†Œ ๊ฐœ์ˆ˜
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ capacity (8 bytes) โ”‚  ํ• ๋‹น๋œ ๊ณต๊ฐ„ ํฌ๊ธฐ
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ”ธ reserve์™€ ๋ฉ”๋ชจ๋ฆฌ ์žฌํ• ๋‹น

๋ฉ”๋ชจ๋ฆฌ ์žฌํ• ๋‹น ๋ฌธ์ œ

std::vector<int> vec;
vec.push_back(1);  // capacity: 1
vec.push_back(2);  // capacity: 2 (๋ฉ”๋ชจ๋ฆฌ ์žฌํ• ๋‹น!)
vec.push_back(3);  // capacity: 4 (๋ฉ”๋ชจ๋ฆฌ ์žฌํ• ๋‹น!)
vec.push_back(4);  // capacity: 4 (์žฌํ• ๋‹น ์—†์Œ)
vec.push_back(5);  // capacity: 8 (๋ฉ”๋ชจ๋ฆฌ ์žฌํ• ๋‹น!)

์žฌํ• ๋‹น ๊ณผ์ •:

1. ์ƒˆ๋กœ์šด ๋” ํฐ ๊ณต๊ฐ„ ํ• ๋‹น (๋ณดํ†ต 2๋ฐฐ)
2. ๊ธฐ์กด ์›์†Œ๋“ค์„ ์ƒˆ ๊ณต๊ฐ„์œผ๋กœ ๋ณต์‚ฌ/์ด๋™ (O(n))
3. ๊ธฐ์กด ๊ณต๊ฐ„ ํ•ด์ œ

๋ฌธ์ œ์ :

  • ๋ฒกํ„ฐ ๋’ค์— ๋‹ค๋ฅธ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ• ๋‹น๋˜์–ด ์žˆ์œผ๋ฉด ํ™•์žฅ ๋ถˆ๊ฐ€
  • ์ƒˆ ๊ณต๊ฐ„ ํ• ๋‹น ํ›„ ์ „์ฒด ๋ณต์‚ฌ/์ด๋™ ๋ฐœ์ƒ
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n)
  • ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฐœ์ƒ

reserve๋กœ ํ•ด๊ฒฐ

std::vector<int> vec;
vec.reserve(100);  // ๋ฏธ๋ฆฌ 100๊ฐœ ๊ณต๊ฐ„ ํ™•๋ณด

for (int i = 0; i < 100; i++)
{
    vec.push_back(i);  // ์žฌํ• ๋‹น ์—†์Œ!
}

reserve์˜ ํšจ๊ณผ:

  • ๋ฉ”๋ชจ๋ฆฌ ์žฌํ• ๋‹น ํšŸ์ˆ˜ ๊ฐ์†Œ
  • ๋ถˆํ•„์š”ํ•œ ๋ณต์‚ฌ/์ด๋™ ์ œ๊ฑฐ
  • ์„ฑ๋Šฅ ํ–ฅ์ƒ

๐Ÿ”ธ noexcept์™€ Move ์ตœ์ ํ™”

๋ฌธ์ œ ์ƒํ™ฉ

class Cat
{
public:
    explicit Cat(std::string name) : mName{std::move(name)}
    {
        std::cout << mName << " Cat constructor" << std::endl;
    }
    
    ~Cat()
    {
        std::cout << mName << " ~Cat()" << std::endl;
    }
    
    Cat(const Cat& other) : mName{other.mName}
    {
        std::cout << mName << " copy constructor" << std::endl;
    }
    
    Cat(Cat&& other) : mName{std::move(other.mName)}
    {
        std::cout << mName << " move constructor" << std::endl;
    }
    
private:
    std::string mName;
};

int main()
{
    std::vector<Cat> cats;
    cats.emplace_back("kitty");
    cats.emplace_back("nabi");
    
    return 0;
}

์ถœ๋ ฅ:

kitty Cat constructor
nabi Cat constructor
kitty copy constructor  โ† โŒ Move๊ฐ€ ์•„๋‹Œ Copy!
kitty ~Cat()
kitty ~Cat()
nabi ~Cat()

์™œ Copy๊ฐ€ ๋ฐœ์ƒํ–ˆ์„๊นŒ?

๋ฉ”๋ชจ๋ฆฌ ์žฌํ• ๋‹น ๊ณผ์ •:

1. kitty ์ถ”๊ฐ€ (capacity: 1)
2. nabi ์ถ”๊ฐ€ ์‹œ๋„
3. capacity ๋ถ€์กฑ โ†’ ์ƒˆ ๊ณต๊ฐ„ ํ• ๋‹น (capacity: 2)
4. kitty๋ฅผ ์ƒˆ ๊ณต๊ฐ„์œผ๋กœ ์ด๋™
   โ†’ ํ•˜์ง€๋งŒ Copy Constructor ํ˜ธ์ถœ๋จ!

์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ Copy๋ฅผ ์„ ํƒํ•˜๋Š” ์ด์œ :

  • Move Constructor์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์›๋ณธ ๋ฐ์ดํ„ฐ๊ฐ€ ์†์ƒ๋  ์ˆ˜ ์žˆ์Œ
  • Copy๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ์›๋ณธ์ด ์•ˆ์ „ํ•จ (Strong Exception Guarantee)
  • ์•ˆ์ „์„ ์œ„ํ•ด Move ๋Œ€์‹  Copy ์„ ํƒ

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 1: noexcept ์ถ”๊ฐ€

class Cat
{
public:
    explicit Cat(std::string name) : mName{std::move(name)}
    {
        std::cout << mName << " Cat constructor" << std::endl;
    }
    
    ~Cat() noexcept
    {
        std::cout << mName << " ~Cat()" << std::endl;
    }
    
    Cat(const Cat& other) : mName{other.mName}
    {
        std::cout << mName << " copy constructor" << std::endl;
    }
    
    Cat(Cat&& other) noexcept  // โœ… noexcept ์ถ”๊ฐ€
        : mName{std::move(other.mName)}
    {
        std::cout << mName << " move constructor" << std::endl;
    }
    
    Cat& operator=(const Cat& other)
    {
        mName = other.mName;
        return *this;
    }
    
    Cat& operator=(Cat&& other) noexcept  // โœ… noexcept ์ถ”๊ฐ€
    {
        mName = std::move(other.mName);
        return *this;
    }
    
private:
    std::string mName;
};

int main()
{
    std::vector<Cat> cats;
    cats.emplace_back("kitty");
    cats.emplace_back("nabi");
    
    return 0;
}

์ถœ๋ ฅ (noexcept ์ถ”๊ฐ€ ํ›„):

kitty Cat constructor
nabi Cat constructor
kitty move constructor  โ† โœ… Move๋กœ ๋ณ€๊ฒฝ!
~Cat()                  โ† ์ด๋™๋œ ์›๋ณธ์˜ ์†Œ๋ฉธ์ž (mName์ด ๋น„์–ด์žˆ์Œ)
kitty ~Cat()            โ† ์ƒˆ ์œ„์น˜์˜ kitty
nabi ~Cat()

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 2: reserve ์‚ฌ์šฉ

int main()
{
    std::vector<Cat> cats;
    cats.reserve(2);  // โœ… ๋ฏธ๋ฆฌ ๊ณต๊ฐ„ ํ™•๋ณด
    
    cats.emplace_back("kitty");
    cats.emplace_back("nabi");
    // ์žฌํ• ๋‹น ์—†์Œ โ†’ Copy/Move ๋ชจ๋‘ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ!
    
    return 0;
}

noexcept๋ฅผ ๋ถ™์—ฌ์•ผ ํ•˜๋Š” ํ•จ์ˆ˜
1. Destructor (์†Œ๋ฉธ์ž)
2. Move Constructor (์ด๋™ ์ƒ์„ฑ์ž)
3. Move Assignment (์ด๋™ ๋Œ€์ž… ์—ฐ์‚ฐ์ž)

์ด์œ :

  • ์œ„ ํ•จ์ˆ˜๋“ค์€ ์ƒˆ๋กœ์šด ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜์ง€ ์•Š์Œ
  • ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ์‹คํŒจ ๋“ฑ์˜ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์—†์Œ
  • noexcept๋ฅผ ๋ช…์‹œํ•˜๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ตœ์ ํ™” ๊ฐ€๋Šฅ

๐Ÿ”ธ Vector for Loop์˜ ํ•จ์ •

์„ธ ๊ฐ€์ง€ ๋ฐ˜๋ณต๋ฌธ ๋ฐฉ์‹

std::vector<int> nums{0, 1, 0, 1};

// 1. Index-based
for (std::size_t idx = 0; idx < nums.size(); idx++)
{
    if (nums[idx] == 0)
    {
        nums.emplace_back(2);
    }
}

// 2. Iterator-based
for (auto itr = nums.begin(); itr != nums.end(); itr++)
{
    if (*itr == 0)
    {
        nums.emplace_back(2);
    }
}

// 3. Range-based
for (auto& num : nums)
{
    if (num == 0)
    {
        nums.emplace_back(2);
    }
}

๊ฒฐ๊ณผ:

  • Index-based: โœ… ์ •์ƒ ๋™์ž‘
  • Iterator-based: โŒ ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ ๋˜๋Š” ๋ฌดํ•œ ๋ฃจํ”„
  • Range-based: โŒ ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ ๋˜๋Š” ํฌ๋ž˜์‹œ

Iterator-based์˜ ๋ฌธ์ œ

std::vector<int> nums{0, 1, 0, 1};  // capacity: 4

for (auto itr = nums.begin(); itr != nums.end(); itr++)
{
    if (*itr == 0)  // ์ฒซ ๋ฒˆ์งธ 0 ๋ฐœ๊ฒฌ
    {
        nums.emplace_back(2);  // capacity ๋ถ€์กฑ โ†’ ์žฌํ• ๋‹น!
        // โŒ ๋ฌธ์ œ: ์žฌํ• ๋‹น์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ ๋ณ€๊ฒฝ
        //    itr์€ ์—ฌ์ „ํžˆ ์˜›๋‚  ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ด (dangling iterator)
        //    nums.end()๋Š” ์ƒˆ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ด
    }
}

Range-based์˜ ๋ฌธ์ œ

Range-based for๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ iterator๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๊ฐ™์€ ๋ฌธ์ œ ๋ฐœ์ƒ

// C++17: Range-based๋Š” ์ด๋ ‡๊ฒŒ ๋ณ€ํ™˜๋จ
{
    auto&& __range = nums;
    auto __begin = __range.begin();
    auto __end = __range.end();
    for (; __begin != __end; ++__begin)
    {
        auto& num = *__begin;
        // capacity ๋ณ€๊ฒฝ ์‹œ __begin๊ณผ __end๊ฐ€ invalidate๋จ
    }
}

Index-based๋Š” ์™œ ์•ˆ์ „ํ•œ๊ฐ€?

for (std::size_t idx = 0; idx < nums.size(); idx++)
{
    if (nums[idx] == 0)
    {
        nums.emplace_back(2);
        // nums.size()๋Š” ๋งค๋ฒˆ ์ƒˆ๋กœ ๊ณ„์‚ฐ๋จ
        // nums[idx]๋Š” ๋งค๋ฒˆ ์ƒˆ ์ฃผ์†Œ์—์„œ ์ ‘๊ทผ
        // โœ… ์žฌํ• ๋‹น๋˜์–ด๋„ ๋ฌธ์ œ์—†์Œ
    }
}

ํ•ต์‹ฌ ๊ทœ์น™

โ— For loop ๋‚ด๋ถ€์—์„œ vector์˜ ํฌ๊ธฐ๊ฐ€ ๋ณ€๊ฒฝ(์ฆ๊ฐ€)๋˜๋ฉด ๋ฐ˜๋“œ์‹œ index-based๋ฅผ ์‚ฌ์šฉ!

// โœ… ์•ˆ์ „: Index-based
for (std::size_t i = 0; i < vec.size(); i++)
{
    vec.push_back(x);  // OK
}

// โŒ ์œ„ํ—˜: Iterator-based
for (auto it = vec.begin(); it != vec.end(); it++)
{
    vec.push_back(x);  // Undefined Behavior ๊ฐ€๋Šฅ!
}

// โŒ ์œ„ํ—˜: Range-based
for (auto& elem : vec)
{
    vec.push_back(x);  // Undefined Behavior ๊ฐ€๋Šฅ!
}

์˜ˆ์™ธ: reserve๋กœ ๋ฏธ๋ฆฌ ๊ณต๊ฐ„ ํ™•๋ณด

std::vector<int> nums{0, 1, 0, 1};
nums.reserve(100);  // ์ถฉ๋ถ„ํ•œ ๊ณต๊ฐ„ ํ™•๋ณด

// โœ… capacity ๋ณ€๊ฒฝ์ด ์—†์œผ๋ฏ€๋กœ iterator๋„ ์•ˆ์ „
for (auto it = nums.begin(); it != nums.end(); it++)
{
    if (*it == 0)
    {
        nums.emplace_back(2);  // ์žฌํ• ๋‹น ์—†์Œ โ†’ ์•ˆ์ „
    }
}

๐Ÿ”ธ erase vs remove (erase-remove idiom)

erase์˜ ๋น„ํšจ์œจ์„ฑ

std::vector<int> nums{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// ์ง์ˆ˜ ์ œ๊ฑฐ (๋น„ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•)
for (auto it = nums.begin(); it != nums.end();)
{
    if (*it % 2 == 0)
    {
        it = nums.erase(it);  // โŒ ๋งค๋ฒˆ ๋’ค์˜ ์›์†Œ๋“ค์„ ์ด๋™
    }
    else
    {
        ++it;
    }
}

erase์˜ ๋™์ž‘:

[1, 2, 3, 4, 5]์—์„œ 2 ์ œ๊ฑฐ:

1. 2 ์ œ๊ฑฐ
2. ๋’ค์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ ์•ž์œผ๋กœ ์ด๋™
   [1, _, 3, 4, 5]
   [1, 3, _, 4, 5]
   [1, 3, 4, _, 5]
   [1, 3, 4, 5, _]
3. size ๊ฐ์†Œ

โ†’ ํ•œ ๋ฒˆ ์ œ๊ฑฐํ•  ๋•Œ๋งˆ๋‹ค O(n)
โ†’ k๊ฐœ ์ œ๊ฑฐ ์‹œ O(n*k)

remove์˜ ํšจ์œจ์ ์ธ ๋™์ž‘

std::vector<int> nums{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// std::remove๋Š” ์ œ๊ฑฐํ•  ์›์†Œ๋ฅผ ๋’ค๋กœ ๋ชจ์Œ
auto new_end = std::remove_if(nums.begin(), nums.end(), 
    [](int n) { return n % 2 == 0; }
);

// ์‹ค์ œ ์ œ๊ฑฐ๋Š” erase๋กœ
nums.erase(new_end, nums.end());

remove์˜ two-pointer ์•Œ๊ณ ๋ฆฌ์ฆ˜:

์ดˆ๊ธฐ: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
       โ†‘
     write (๋ณต์‚ฌํ•  ์œ„์น˜)
       โ†‘
     read (ํ™•์ธํ•  ์œ„์น˜)

1. read=1 (ํ™€์ˆ˜) โ†’ write ์œ„์น˜์— ๋ณต์‚ฌ, ๋‘˜ ๋‹ค ์ „์ง„
   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
       โ†‘
     write
       โ†‘
     read

2. read=2 (์ง์ˆ˜) โ†’ ๋ณต์‚ฌ ์•ˆ ํ•จ, read๋งŒ ์ „์ง„
   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
       โ†‘
     write
          โ†‘
         read

3. read=3 (ํ™€์ˆ˜) โ†’ write์— ๋ณต์‚ฌ, ๋‘˜ ๋‹ค ์ „์ง„
   [1, 3, 3, 4, 5, 6, 7, 8, 9, 10]
          โ†‘
        write
             โ†‘
           read

4. ๋ฐ˜๋ณต...

์ตœ์ข…: [1, 3, 5, 7, 9, 6, 7, 8, 9, 10]
                     โ†‘
                   new_end (๋ฐ˜ํ™˜๊ฐ’)

โ†’ new_end๋ถ€ํ„ฐ end()๊นŒ์ง€ erase
โ†’ ์ด O(n) ํ•œ ๋ฒˆ๋งŒ!

erase-remove idiom (ํ‘œ์ค€ ํŒจํ„ด)

// โœ… ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•
nums.erase(
    std::remove_if(nums.begin(), nums.end(), 
        [](int n) { return n % 2 == 0; }
    ),
    nums.end()
);

// ํ•œ ์ค„๋กœ ํ‘œํ˜„ ๊ฐ€๋Šฅ

์„ฑ๋Šฅ ๋น„๊ต:

  • erase ๋ฐ˜๋ณต: O(n*k) - k๋Š” ์ œ๊ฑฐํ•  ์›์†Œ ๊ฐœ์ˆ˜
  • erase-remove idiom: O(n) - ๋‹จ ํ•œ ๋ฒˆ์˜ ์ˆœํšŒ

C++20: std::erase_if

// C++20๋ถ€ํ„ฐ๋Š” ๋” ๊ฐ„๋‹จ
std::erase_if(nums, [](int n) { return n % 2 == 0; });

๐Ÿ”ธ Vector ์•Œ๊ณ ๋ฆฌ์ฆ˜

์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

std::sort (์ผ๋ฐ˜ ์ •๋ ฌ)

#include <algorithm>

std::vector<int> nums{5, 2, 8, 1, 9, 3};

std::sort(nums.begin(), nums.end());
// nums: {1, 2, 3, 5, 8, 9}

// ๋‚ด๋ฆผ์ฐจ์ˆœ
std::sort(nums.begin(), nums.end(), std::greater<int>{});
// nums: {9, 8, 5, 3, 2, 1}

// ์ปค์Šคํ…€ ๋น„๊ต
std::sort(nums.begin(), nums.end(), [](int a, int b) {
    return std::abs(a) < std::abs(b);  // ์ ˆ๋Œ“๊ฐ’ ๊ธฐ์ค€
});

์‹œ๊ฐ„ ๋ณต์žก๋„: O(n log n)

std::stable_sort (์•ˆ์ • ์ •๋ ฌ)

struct Person
{
    std::string name;
    int age;
};

std::vector<Person> people{
    {"Alice", 25},
    {"Bob", 30},
    {"Charlie", 25},
    {"David", 30}
};

// ๋‚˜์ด ๊ธฐ์ค€ ์ •๋ ฌ
std::stable_sort(people.begin(), people.end(), 
    [](const Person& a, const Person& b) {
        return a.age < b.age;
    }
);

// stable_sort: ๋‚˜์ด๊ฐ€ ๊ฐ™์œผ๋ฉด ์›๋ž˜ ์ˆœ์„œ ์œ ์ง€
// Alice(25), Charlie(25), Bob(30), David(30)

// sort: ๋‚˜์ด๊ฐ€ ๊ฐ™์œผ๋ฉด ์ˆœ์„œ ๋ณด์žฅ ์•ˆ ๋จ
// Charlie(25), Alice(25), David(30), Bob(30) ๊ฐ€๋Šฅ

stable_sort์˜ ํŠน์ง•:

  • ๋™์ผํ•œ ๊ฐ’์˜ ์›์†Œ๋“ค์˜ ์ƒ๋Œ€์  ์ˆœ์„œ ์œ ์ง€
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n log n) (merge sort ๊ธฐ๋ฐ˜์œผ๋กœ ์ถ”์ธก)
  • sort๋ณด๋‹ค ์•ฝ๊ฐ„ ๋А๋ฆฌ์ง€๋งŒ ์•ˆ์ •์„ฑ ๋ณด์žฅ

std::partial_sort (๋ถ€๋ถ„ ์ •๋ ฌ)

std::vector<int> nums{5, 2, 8, 1, 9, 3, 7, 4, 6};

// ์ฒ˜์Œ 3๊ฐœ๋งŒ ์ •๋ ฌ
std::partial_sort(nums.begin(), nums.begin() + 3, nums.end());
// nums: {1, 2, 3, ?, ?, ?, ?, ?, ?}
//        โ†‘์ •๋ ฌ๋จ  โ†‘์ •๋ ฌ ์•ˆ ๋จ (์ˆœ์„œ ๋ถˆํ™•์ •)

// ์‹ค์ œ: {1, 2, 3, 8, 9, 5, 7, 4, 6}

์‚ฌ์šฉ ์‚ฌ๋ก€:

  • Top K ๋ฌธ์ œ (์ƒ์œ„ K๊ฐœ๋งŒ ํ•„์š”)
  • ์ „์ฒด ์ •๋ ฌ๋ณด๋‹ค ๋น ๋ฆ„
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n log k) - k๋Š” ๋ถ€๋ถ„ ์ •๋ ฌํ•  ๊ฐœ์ˆ˜

std::nth_element

std::vector<int> nums{5, 2, 8, 1, 9, 3, 7, 4, 6};

// ์ค‘์•™๊ฐ’ ์ฐพ๊ธฐ (5๋ฒˆ์งธ๋กœ ์ž‘์€ ์›์†Œ)
std::nth_element(nums.begin(), nums.begin() + 4, nums.end());
// nums[4]๋Š” ์ •ํ™•ํžˆ 5๋ฒˆ์งธ๋กœ ์ž‘์€ ์›์†Œ
// nums[4] ์™ผ์ชฝ์€ ๋ชจ๋‘ ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์Œ
// nums[4] ์˜ค๋ฅธ์ชฝ์€ ๋ชจ๋‘ ํฌ๊ฑฐ๋‚˜ ๊ฐ™์Œ
// ํ•˜์ง€๋งŒ ์–‘์ชฝ์ด ์ •๋ ฌ๋œ ๊ฒƒ์€ ์•„๋‹˜

std::cout << nums[4] << std::endl;  // 5 (์ค‘์•™๊ฐ’)

ํŠน์ง•:

  • n๋ฒˆ์งธ ์›์†Œ๋งŒ ์ •ํ™•ํ•œ ์œ„์น˜์— ๋ฐฐ์น˜
  • ์–‘์ชฝ์€ ์ •๋ ฌ๋˜์ง€ ์•Š์Œ
  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n) (ํ‰๊ท )
  • ์ค‘์•™๊ฐ’, ๋ฐฑ๋ถ„์œ„์ˆ˜ ์ฐพ๊ธฐ์— ์œ ์šฉ

์ตœ์†Ÿ๊ฐ’/์ตœ๋Œ“๊ฐ’ ์ฐพ๊ธฐ

std::vector<int> nums{5, 2, 8, 1, 9, 3};

// ์ตœ์†Ÿ๊ฐ’
auto min_it = std::min_element(nums.begin(), nums.end());
std::cout << *min_it << std::endl;  // 1

// ์ตœ๋Œ“๊ฐ’
auto max_it = std::max_element(nums.begin(), nums.end());
std::cout << *max_it << std::endl;  // 9

// ์ตœ์†Ÿ๊ฐ’๊ณผ ์ตœ๋Œ“๊ฐ’ ๋™์‹œ์—
auto [min_it2, max_it2] = std::minmax_element(nums.begin(), nums.end());
std::cout << *min_it2 << ", " << *max_it2 << std::endl;  // 1, 9

// ์ธ๋ฑ์Šค ์ฐพ๊ธฐ
auto min_idx = std::distance(nums.begin(), min_it);
std::cout << "Min index: " << min_idx << std::endl;  // 3

std::distance

  • Iterator ๊ฐ„์˜ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ
  • ์ธ๋ฑ์Šค๋ฅผ ๊ตฌํ•  ๋•Œ ์œ ์šฉ
auto it = std::find(nums.begin(), nums.end(), 8);
if (it != nums.end())
{
    std::size_t index = std::distance(nums.begin(), it);
    std::cout << "Found at index: " << index << std::endl;
}

ํ•ฉ๊ณ„ ๋ฐ ๋ˆ„์  ์—ฐ์‚ฐ

std::accumulate

#include <numeric>

std::vector<int> nums{1, 2, 3, 4, 5};

// ํ•ฉ๊ณ„
int sum = std::accumulate(nums.begin(), nums.end(), 0);
std::cout << sum << std::endl;  // 15

// ๊ณฑ์…ˆ
int product = std::accumulate(nums.begin(), nums.end(), 1,
    [](int acc, int n) { return acc * n; }
);
std::cout << product << std::endl;  // 120

// ๋ฌธ์ž์—ด ์—ฐ๊ฒฐ
std::vector<std::string> words{"Hello", " ", "World"};
std::string result = std::accumulate(words.begin(), words.end(), 
    std::string{},
    [](std::string acc, const std::string& s) { return acc + s; }
);
std::cout << result << std::endl;  // "Hello World"

std::reduce (C++17)

// std::accumulate์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๋ณ‘๋ ฌ ์‹คํ–‰ ๊ฐ€๋Šฅ
int sum = std::reduce(std::execution::par,  // ๋ณ‘๋ ฌ ์‹คํ–‰
    nums.begin(), nums.end(), 0
);

์ฐจ์ด์ :

  • accumulate: ์ˆœ์ฐจ ์‹คํ–‰, ์ˆœ์„œ ๋ณด์žฅ
  • reduce: ๋ณ‘๋ ฌ ์‹คํ–‰ ๊ฐ€๋Šฅ, ์ˆœ์„œ ๋ณด์žฅ ์•ˆ ๋จ (๊ฒฐํ•ฉ ๋ฒ•์น™ ํ•„์š”)

๐Ÿ”ธ ํ•ต์‹ฌ ์ •๋ฆฌ

Vector ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

  • Vector ๊ฐ์ฒด: 24 bytes (ํฌ์ธํ„ฐ + size + capacity)
  • reserve()๋กœ ์žฌํ• ๋‹น ๋ฐฉ์ง€
  • noexcept๋กœ move ์ตœ์ ํ™”

๋ฐ˜๋ณต๋ฌธ ์ฃผ์˜์‚ฌํ•ญ

  • Loop ๋‚ด๋ถ€์—์„œ ํฌ๊ธฐ ๋ณ€๊ฒฝ ์‹œ ๋ฐ˜๋“œ์‹œ index-based ์‚ฌ์šฉ
  • Iterator์™€ Range-based๋Š” ์žฌํ• ๋‹น ์‹œ dangling

ํšจ์œจ์ ์ธ ์‚ญ์ œ

  • erase ๋ฐ˜๋ณต: O(n*k)
  • erase-remove idiom: O(n)
  • C++20: std::erase_if

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ํƒ

  • ์ „์ฒด ์ •๋ ฌ: std::sort O(n log n)
  • ์•ˆ์ • ์ •๋ ฌ: std::stable_sort O(n log n)
  • ๋ถ€๋ถ„ ์ •๋ ฌ: std::partial_sort O(n log k)
  • n๋ฒˆ์งธ ์›์†Œ: std::nth_element O(n)
  • ์ตœ์†Ÿ๊ฐ’/์ตœ๋Œ“๊ฐ’: std::min_element / std::max_element O(n)

<์ฐธ๊ณ  ์ž๋ฃŒ>

์ฝ”๋“œ์—†๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ
C++ std::vector
C++ Algorithms Library

0๊ฐœ์˜ ๋Œ“๊ธ€