Repository: Alinshans/MyTinySTL
Branch: master
Commit: f86437ecffe8
Files: 59
Total size: 620.5 KB
Directory structure:
gitextract_bjpk8nmi/
├── .gitattributes
├── .gitignore
├── .travis.yml
├── CMakeLists.txt
├── License.txt
├── MSVC/
│ ├── MyTinySTL_VS2015.sln
│ ├── MyTinySTL_VS2015.vcxproj
│ └── MyTinySTL_VS2015.vcxproj.filters
├── MyTinySTL/
│ ├── algo.h
│ ├── algobase.h
│ ├── algorithm.h
│ ├── alloc.h
│ ├── allocator.h
│ ├── astring.h
│ ├── basic_string.h
│ ├── construct.h
│ ├── deque.h
│ ├── exceptdef.h
│ ├── functional.h
│ ├── hashtable.h
│ ├── heap_algo.h
│ ├── iterator.h
│ ├── list.h
│ ├── map.h
│ ├── memory.h
│ ├── numeric.h
│ ├── queue.h
│ ├── rb_tree.h
│ ├── set.h
│ ├── set_algo.h
│ ├── stack.h
│ ├── stream_iterator.h
│ ├── type_traits.h
│ ├── uninitialized.h
│ ├── unordered_map.h
│ ├── unordered_set.h
│ ├── util.h
│ └── vector.h
├── README.md
├── Test/
│ ├── CMakeLists.txt
│ ├── Lib/
│ │ └── redbud/
│ │ ├── io/
│ │ │ └── color.h
│ │ └── platform.h
│ ├── README.md
│ ├── algorithm_performance_test.h
│ ├── algorithm_test.h
│ ├── deque_test.h
│ ├── iterator_test.h
│ ├── list_test.h
│ ├── map_test.h
│ ├── queue_test.h
│ ├── set_test.h
│ ├── stack_test.h
│ ├── string_test.h
│ ├── test.cpp
│ ├── test.h
│ ├── unordered_map_test.h
│ ├── unordered_set_test.h
│ └── vector_test.h
└── appveyor.yml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# Local build files
*c.cmd
*a.exe
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
[Xx]64/
[Xx]86/
[Bb]uild/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Visual Studio Code
.vscode/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Un-comment the next line if you do not want to checkin
# your web deploy settings because they may include unencrypted
# passwords
#*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# LightSwitch generated files
GeneratedArtifacts/
ModelManifest.xml
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/
================================================
FILE: .travis.yml
================================================
language: cpp
# ubuntu 14.04 version
sudo: required
dist: trusty
matrix:
include:
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5']
env:
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6']
env:
- MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7']
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- os: osx
osx_image: xcode5
env:
- MATRIX_EVAL="CC=clang && CXX=clang++"
- os: osx
osx_image: xcode6
env:
- MATRIX_EVAL="CC=clang && CXX=clang++"
- os: osx
osx_image: xcode7
env:
- MATRIX_EVAL="CC=clang && CXX=clang++"
- os: osx
osx_image: xcode8
env:
- MATRIX_EVAL="CC=clang && CXX=clang++"
before_script:
- eval "${MATRIX_EVAL}"
- $CXX --version
script:
- mkdir build && cd ./build
- cmake ..
- make
- cd ../bin && ./stltest
branches:
only:
- master
notifications:
email: false
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 2.8)
project(MyTinySTL)
# version
set(MyTinySTL_VERSION_MAJOR 2)
set(MyTinySTL_VERSION_MINOR 0)
set(MyTinySTL_VERSION_PATCH 0)
set(MyTinySTL_VERSION "${MyTinySTL_VERSION_MAJOR}.${MyTinySTL_VERSION_MINOR}.${MyTinySTL_VERSION_PATCH}")
message(STATUS "The version of this project is: ${MyTinySTL_VERSION}")
# build type
set(CMAKE_BUILD_TYPE release)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall -Wextra -Wno-sign-compare -Wno-unused-but-set-variable -Wno-array-bounds")
# set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wsign-conversion)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0")
message(FATAL_ERROR "required GCC 5.0 or later")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall -Wextra -Wno-sign-compare")
# set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wimplicit-fallthrough)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.5.0")
message(FATAL_ERROR "required Clang 3.5 or later")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
endif()
message(STATUS "The cmake_cxx_flags is: ${CMAKE_CXX_FLAGS}")
add_subdirectory(${PROJECT_SOURCE_DIR}/Test)
================================================
FILE: License.txt
================================================
Copyright (c) 2016-2017 Alinshans. All rights reserved.
First published on github, see https://github.com/Alinshans/MyTinySTL
The MyTinySTL source code is licensed under the MIT License.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: MSVC/MyTinySTL_VS2015.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyTinySTL", "MyTinySTL_VS2015.vcxproj", "{E88807F6-B07C-4371-BD38-FB1569F894E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E88807F6-B07C-4371-BD38-FB1569F894E4}.Debug|x64.ActiveCfg = Debug|x64
{E88807F6-B07C-4371-BD38-FB1569F894E4}.Debug|x64.Build.0 = Debug|x64
{E88807F6-B07C-4371-BD38-FB1569F894E4}.Debug|x86.ActiveCfg = Debug|Win32
{E88807F6-B07C-4371-BD38-FB1569F894E4}.Debug|x86.Build.0 = Debug|Win32
{E88807F6-B07C-4371-BD38-FB1569F894E4}.Release|x64.ActiveCfg = Release|x64
{E88807F6-B07C-4371-BD38-FB1569F894E4}.Release|x64.Build.0 = Release|x64
{E88807F6-B07C-4371-BD38-FB1569F894E4}.Release|x86.ActiveCfg = Release|Win32
{E88807F6-B07C-4371-BD38-FB1569F894E4}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
================================================
FILE: MSVC/MyTinySTL_VS2015.vcxproj
================================================
Debug
Win32
Release
Win32
Debug
x64
Release
x64
{E88807F6-B07C-4371-BD38-FB1569F894E4}
Win32Proj
MyTinySTL
8.1
MyTinySTL
Application
true
v140
Unicode
Application
false
v140
true
Unicode
Application
true
v140
Unicode
Application
false
v140
true
Unicode
true
true
false
false
Level3
Disabled
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
Console
true
Level4
Disabled
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
Console
true
Level3
MaxSpeed
true
true
WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
Console
true
true
true
Level4
MaxSpeed
true
true
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
Console
true
true
true
================================================
FILE: MSVC/MyTinySTL_VS2015.vcxproj.filters
================================================
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
{93995380-89BD-4b04-88EB-625FBE52EBFB}
h;hh;hpp;hxx;hm;inl;inc;xsd
{4FC737F1-C7A5-4376-A066-2A32D752A2FF}
cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
{ec314ff3-dcde-4cac-a63a-4f6827750d0a}
{c6f24d77-e6f0-439e-954a-c0ca577689d5}
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
include
test
test
test
test
test
test
test
test
test
test
test
test
test
test\Lib
test\Lib
include
include
include
test
================================================
FILE: MyTinySTL/algo.h
================================================
#ifndef MYTINYSTL_ALGO_H_
#define MYTINYSTL_ALGO_H_
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4244)
#endif
// 这个头文件包含了 mystl 的一系列算法
#include
#include
#include "algobase.h"
#include "memory.h"
#include "heap_algo.h"
#include "functional.h"
namespace mystl
{
/*****************************************************************************************/
// all_of
// 检查[first, last)内是否全部元素都满足一元操作 unary_pred 为 true 的情况,满足则返回 true
/*****************************************************************************************/
template
bool all_of(InputIter first, InputIter last, UnaryPredicate unary_pred)
{
for (; first != last; ++first)
{
if (!unary_pred(*first))
return false;
}
return true;
}
/*****************************************************************************************/
// any_of
// 检查[first, last)内是否存在某个元素满足一元操作 unary_pred 为 true 的情况,满足则返回 true
/*****************************************************************************************/
template
bool any_of(InputIter first, InputIter last, UnaryPredicate unary_pred)
{
for (; first != last; ++first)
{
if (unary_pred(*first))
return true;
}
return false;
}
/*****************************************************************************************/
// none_of
// 检查[first, last)内是否全部元素都不满足一元操作 unary_pred 为 true 的情况,满足则返回 true
/*****************************************************************************************/
template
bool none_of(InputIter first, InputIter last, UnaryPredicate unary_pred)
{
for (; first != last; ++first)
{
if (unary_pred(*first))
return false;
}
return true;
}
/*****************************************************************************************/
// count
// 对[first, last)区间内的元素与给定值进行比较,缺省使用 operator==,返回元素相等的个数
/*****************************************************************************************/
template
size_t count(InputIter first, InputIter last, const T& value)
{
size_t n = 0;
for (; first != last; ++first)
{
if (*first == value)
++n;
}
return n;
}
/*****************************************************************************************/
// count_if
// 对[first, last)区间内的每个元素都进行一元 unary_pred 操作,返回结果为 true 的个数
/*****************************************************************************************/
template
size_t count_if(InputIter first, InputIter last, UnaryPredicate unary_pred)
{
size_t n = 0;
for (; first != last; ++first)
{
if (unary_pred(*first))
++n;
}
return n;
}
/*****************************************************************************************/
// find
// 在[first, last)区间内找到等于 value 的元素,返回指向该元素的迭代器
/*****************************************************************************************/
template
InputIter
find(InputIter first, InputIter last, const T& value)
{
while (first != last && *first != value)
++first;
return first;
}
/*****************************************************************************************/
// find_if
// 在[first, last)区间内找到第一个令一元操作 unary_pred 为 true 的元素并返回指向该元素的迭代器
/*****************************************************************************************/
template
InputIter
find_if(InputIter first, InputIter last, UnaryPredicate unary_pred)
{
while (first != last && !unary_pred(*first))
++first;
return first;
}
/*****************************************************************************************/
// find_if_not
// 在[first, last)区间内找到第一个令一元操作 unary_pred 为 false 的元素并返回指向该元素的迭代器
/*****************************************************************************************/
template
InputIter
find_if_not(InputIter first, InputIter last, UnaryPredicate unary_pred)
{
while (first != last && unary_pred(*first))
++first;
return first;
}
/*****************************************************************************************/
// search
// 在[first1, last1)中查找[first2, last2)的首次出现点
/*****************************************************************************************/
template
ForwardIter1
search(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2)
{
auto d1 = mystl::distance(first1, last1);
auto d2 = mystl::distance(first2, last2);
if (d1 < d2)
return last1;
auto current1 = first1;
auto current2 = first2;
while (current2 != last2)
{
if (*current1 == *current2)
{
++current1;
++current2;
}
else
{
if (d1 == d2)
{
return last1;
}
else
{
current1 = ++first1;
current2 = first2;
--d1;
}
}
}
return first1;
}
// 重载版本使用函数对象 comp 代替比较操作
template
ForwardIter1
search(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2, Compared comp)
{
auto d1 = mystl::distance(first1, last1);
auto d2 = mystl::distance(first2, last2);
if (d1 < d2)
return last1;
auto current1 = first1;
auto current2 = first2;
while (current2 != last2)
{
if (comp(*current1, *current2))
{
++current1;
++current2;
}
else
{
if (d1 == d2)
{
return last1;
}
else
{
current1 = ++first1;
current2 = first2;
--d1;
}
}
}
return first1;
}
/*****************************************************************************************/
// search_n
// 在[first, last)中查找连续 n 个 value 所形成的子序列,返回一个迭代器指向该子序列的起始处
/*****************************************************************************************/
template
ForwardIter
search_n(ForwardIter first, ForwardIter last, Size n, const T& value)
{
if (n <= 0)
{
return first;
}
else
{
first = mystl::find(first, last, value);
while (first != last)
{
auto m = n - 1;
auto i = first;
++i;
while (i != last && m != 0 && *i == value)
{
++i;
--m;
}
if (m == 0)
{
return first;
}
else
{
first = mystl::find(i, last, value);
}
}
return last;
}
}
// 重载版本使用函数对象 comp 代替比较操作
template
ForwardIter
search_n(ForwardIter first, ForwardIter last,
Size n, const T& value, Compared comp)
{
if (n <= 0)
{
return first;
}
else
{
while (first != last)
{
if (comp(*first, value))
break;
++first;
}
while (first != last)
{
auto m = n - 1;
auto i = first;
++i;
while (i != last && m != 0 && comp(*i, value))
{
++i;
--m;
}
if (m == 0)
{
return first;
}
else
{
while (i != last)
{
if (comp(*i, value))
break;
++i;
}
first = i;
}
}
return last;
}
}
/*****************************************************************************************/
// find_end
// 在[first1, last1)区间中查找[first2, last2)最后一次出现的地方,若不存在返回 last1
/*****************************************************************************************/
// find_end_dispatch 的 forward_iterator_tag 版本
template
ForwardIter1
find_end_dispatch(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
forward_iterator_tag, forward_iterator_tag)
{
if (first2 == last2)
{
return last1;
}
else
{
auto result = last1;
while (true)
{
// 利用 search 查找某个子序列的首次出现点,找不到则返回 last1
auto new_result = mystl::search(first1, last1, first2, last2);
if (new_result == last1)
{
return result;
}
else
{
result = new_result;
first1 = new_result;
++first1;
}
}
}
}
// find_end_dispatch 的 bidirectional_iterator_tag 版本
template
BidirectionalIter1
find_end_dispatch(BidirectionalIter1 first1, BidirectionalIter1 last1,
BidirectionalIter2 first2, BidirectionalIter2 last2,
bidirectional_iterator_tag, bidirectional_iterator_tag)
{
typedef reverse_iterator reviter1;
typedef reverse_iterator reviter2;
reviter1 rlast1(first1);
reviter2 rlast2(first2);
reviter1 rresult = mystl::search(reviter1(last1), rlast1, reviter2(last2), rlast2);
if (rresult == rlast1)
{
return last1;
}
else
{
auto result = rresult.base();
mystl::advance(result, -mystl::distance(first2, last2));
return result;
}
}
template
ForwardIter1
find_end(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2)
{
typedef typename iterator_traits::iterator_category Category1;
typedef typename iterator_traits::iterator_category Category2;
return mystl::find_end_dispatch(first1, last1, first2, last2, Category1(), Category2());
}
// 重载版本使用函数对象 comp 代替比较操作
// find_end_dispatch 的 forward_iterator_tag 版本
template
ForwardIter1
find_end_dispatch(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
forward_iterator_tag, forward_iterator_tag, Compared comp)
{
if (first2 == last2)
{
return last1;
}
else
{
auto result = last1;
while (true)
{
// 利用 search 查找某个子序列的首次出现点,找不到则返回 last1
auto new_result = mystl::search(first1, last1, first2, last2, comp);
if (new_result == last1)
{
return result;
}
else
{
result = new_result;
first1 = new_result;
++first1;
}
}
}
}
// find_end_dispatch 的 bidirectional_iterator_tag 版本
template
BidirectionalIter1
find_end_dispatch(BidirectionalIter1 first1, BidirectionalIter1 last1,
BidirectionalIter2 first2, BidirectionalIter2 last2,
bidirectional_iterator_tag, bidirectional_iterator_tag, Compared comp)
{
typedef reverse_iterator reviter1;
typedef reverse_iterator reviter2;
reviter1 rlast1(first1);
reviter2 rlast2(first2);
reviter1 rresult = mystl::search(reviter1(last1), rlast1, reviter2(last2), rlast2, comp);
if (rresult == rlast1)
{
return last1;
}
else
{
auto result = rresult.base();
mystl::advance(result, -mystl::distance(first2, last2));
return result;
}
}
template
ForwardIter1
find_end(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2, Compared comp)
{
typedef typename iterator_traits::iterator_category Category1;
typedef typename iterator_traits::iterator_category Category2;
return mystl::find_end_dispatch(first1, last1, first2, last2, Category1(), Category2(), comp);
}
/*****************************************************************************************/
// find_first_of
// 在[first1, last1)中查找[first2, last2)中的某些元素,返回指向第一次出现的元素的迭代器
/*****************************************************************************************/
template
InputIter
find_first_of(InputIter first1, InputIter last1,
ForwardIter first2, ForwardIter last2)
{
for (; first1 != last1; ++first1)
{
for (auto iter = first2; iter != last2; ++iter)
{
if (*first1 == *iter)
return first1;
}
}
return last1;
}
// 重载版本使用函数对象 comp 代替比较操作
template
InputIter
find_first_of(InputIter first1, InputIter last1,
ForwardIter first2, ForwardIter last2, Compared comp)
{
for (; first1 != last1; ++first1)
{
for (auto iter = first2; iter != last2; ++iter)
{
if (comp(*first1, *iter))
return first1;
}
}
return last1;
}
/*****************************************************************************************/
// for_each
// 使用一个函数对象 f 对[first, last)区间内的每个元素执行一个 operator() 操作,但不能改变元素内容
// f() 可返回一个值,但该值会被忽略
/*****************************************************************************************/
template
Function for_each(InputIter first, InputIter last, Function f)
{
for (; first != last; ++first)
{
f(*first);
}
return f;
}
/*****************************************************************************************/
// adjacent_find
// 找出第一对匹配的相邻元素,缺省使用 operator== 比较,如果找到返回一个迭代器,指向这对元素的第一个元素
/*****************************************************************************************/
template
ForwardIter adjacent_find(ForwardIter first, ForwardIter last)
{
if (first == last) return last;
auto next = first;
while (++next != last)
{
if (*first == *next) return first;
first = next;
}
return last;
}
// 重载版本使用函数对象 comp 代替比较操作
template
ForwardIter adjacent_find(ForwardIter first, ForwardIter last, Compared comp)
{
if (first == last) return last;
auto next = first;
while (++next != last)
{
if (comp(*first, *next)) return first;
first = next;
}
return last;
}
/*****************************************************************************************/
// lower_bound
// 在[first, last)中查找第一个不小于 value 的元素,并返回指向它的迭代器,若没有则返回 last
/*****************************************************************************************/
// lbound_dispatch 的 forward_iterator_tag 版本
template
ForwardIter
lbound_dispatch(ForwardIter first, ForwardIter last,
const T& value, forward_iterator_tag)
{
auto len = mystl::distance(first, last);
auto half = len;
ForwardIter middle;
while (len > 0)
{
half = len >> 1;
middle = first;
mystl::advance(middle, half);
if (*middle < value)
{
first = middle;
++first;
len = len - half - 1;
}
else
{
len = half;
}
}
return first;
}
// lbound_dispatch 的 random_access_iterator_tag 版本
template
RandomIter
lbound_dispatch(RandomIter first, RandomIter last,
const T& value, random_access_iterator_tag)
{
auto len = last - first;
auto half = len;
RandomIter middle;
while (len > 0)
{
half = len >> 1;
middle = first + half;
if (*middle < value)
{
first = middle + 1;
len = len - half - 1;
}
else
{
len = half;
}
}
return first;
}
template
ForwardIter
lower_bound(ForwardIter first, ForwardIter last, const T& value)
{
return mystl::lbound_dispatch(first, last, value, iterator_category(first));
}
// 重载版本使用函数对象 comp 代替比较操作
// lbound_dispatch 的 forward_iterator_tag 版本
template
ForwardIter
lbound_dispatch(ForwardIter first, ForwardIter last,
const T& value, forward_iterator_tag, Compared comp)
{
auto len = mystl::distance(first, last);
auto half = len;
ForwardIter middle;
while (len > 0)
{
half = len >> 1;
middle = first;
mystl::advance(middle, half);
if (comp(*middle, value))
{
first = middle;
++first;
len = len - half - 1;
}
else
{
len = half;
}
}
return first;
}
// lbound_dispatch 的 random_access_iterator_tag 版本
template
RandomIter
lbound_dispatch(RandomIter first, RandomIter last,
const T& value, random_access_iterator_tag, Compared comp)
{
auto len = last - first;
auto half = len;
RandomIter middle;
while (len > 0)
{
half = len >> 1;
middle = first + half;
if (comp(*middle, value))
{
first = middle + 1;
len = len - half - 1;
}
else
{
len = half;
}
}
return first;
}
template
ForwardIter
lower_bound(ForwardIter first, ForwardIter last, const T& value, Compared comp)
{
return mystl::lbound_dispatch(first, last, value, iterator_category(first), comp);
}
/*****************************************************************************************/
// upper_bound
// 在[first, last)中查找第一个大于value 的元素,并返回指向它的迭代器,若没有则返回 last
/*****************************************************************************************/
// ubound_dispatch 的 forward_iterator_tag 版本
template
ForwardIter
ubound_dispatch(ForwardIter first, ForwardIter last,
const T& value, forward_iterator_tag)
{
auto len = mystl::distance(first, last);
auto half = len;
ForwardIter middle;
while (len > 0)
{
half = len >> 1;
middle = first;
mystl::advance(middle, half);
if (value < *middle)
{
len = half;
}
else
{
first = middle;
++first;
len = len - half - 1;
}
}
return first;
}
// ubound_dispatch 的 random_access_iterator_tag 版本
template
RandomIter
ubound_dispatch(RandomIter first, RandomIter last,
const T& value, random_access_iterator_tag)
{
auto len = last - first;
auto half = len;
RandomIter middle;
while (len > 0)
{
half = len >> 1;
middle = first + half;
if (value < *middle)
{
len = half;
}
else
{
first = middle + 1;
len = len - half - 1;
}
}
return first;
}
template
ForwardIter
upper_bound(ForwardIter first, ForwardIter last, const T& value)
{
return mystl::ubound_dispatch(first, last, value, iterator_category(first));
}
// 重载版本使用函数对象 comp 代替比较操作
// ubound_dispatch 的 forward_iterator_tag 版本
template
ForwardIter
ubound_dispatch(ForwardIter first, ForwardIter last,
const T& value, forward_iterator_tag, Compared comp)
{
auto len = mystl::distance(first, last);
auto half = len;
ForwardIter middle;
while (len > 0)
{
half = len >> 1;
middle = first;
mystl::advance(middle, half);
if (comp(value, *middle))
{
len = half;
}
else
{
first = middle;
++first;
len = len - half - 1;
}
}
return first;
}
// ubound_dispatch 的 random_access_iterator_tag 版本
template
RandomIter
ubound_dispatch(RandomIter first, RandomIter last,
const T& value, random_access_iterator_tag, Compared comp)
{
auto len = last - first;
auto half = len;
RandomIter middle;
while (len > 0)
{
half = len >> 1;
middle = first + half;
if (comp(value, *middle))
{
len = half;
}
else
{
first = middle + 1;
len = len - half - 1;
}
}
return first;
}
template
ForwardIter
upper_bound(ForwardIter first, ForwardIter last, const T& value, Compared comp)
{
return mystl::ubound_dispatch(first, last, value, iterator_category(first), comp);
}
/*****************************************************************************************/
// binary_search
// 二分查找,如果在[first, last)内有等同于 value 的元素,返回 true,否则返回 false
/*****************************************************************************************/
template
bool binary_search(ForwardIter first, ForwardIter last, const T& value)
{
auto i = mystl::lower_bound(first, last, value);
return i != last && !(value < *i);
}
// 重载版本使用函数对象 comp 代替比较操作
template
bool binary_search(ForwardIter first, ForwardIter last, const T& value, Compared comp)
{
auto i = mystl::lower_bound(first, last, value);
return i != last && !comp(value, *i);
}
/*****************************************************************************************/
// equal_range
// 查找[first,last)区间中与 value 相等的元素所形成的区间,返回一对迭代器指向区间首尾
// 第一个迭代器指向第一个不小于 value 的元素,第二个迭代器指向第一个大于 value 的元素
/*****************************************************************************************/
// erange_dispatch 的 forward_iterator_tag 版本
template
mystl::pair
erange_dispatch(ForwardIter first, ForwardIter last,
const T& value, forward_iterator_tag)
{
auto len = mystl::distance(first, last);
auto half = len;
ForwardIter middle, left, right;
while (len > 0)
{
half = len >> 1;
middle = first;
mystl::advance(middle, half);
if (*middle < value)
{
first = middle;
++first;
len = len - half - 1;
}
else if (value < *middle)
{
len = half;
}
else
{
left = mystl::lower_bound(first, last, value);
mystl::advance(first, len);
right = mystl::upper_bound(++middle, first, value);
return mystl::pair(left, right);
}
}
return mystl::pair(last, last);
}
// erange_dispatch 的 random_access_iterator_tag 版本
template
mystl::pair
erange_dispatch(RandomIter first, RandomIter last,
const T& value, random_access_iterator_tag)
{
auto len = last - first;
auto half = len;
RandomIter middle, left, right;
while (len > 0)
{
half = len >> 1;
middle = first + half;
if (*middle < value)
{
first = middle + 1;
len = len - half - 1;
}
else if (value < *middle)
{
len = half;
}
else
{
left = mystl::lower_bound(first, middle, value);
right = mystl::upper_bound(++middle, first + len, value);
return mystl::pair(left, right);
}
}
return mystl::pair(last, last);
}
template
mystl::pair
equal_range(ForwardIter first, ForwardIter last, const T& value)
{
return mystl::erange_dispatch(first, last, value, iterator_category(first));
}
// 重载版本使用函数对象 comp 代替比较操作
// erange_dispatch 的 forward iterator 版本
template
mystl::pair
erange_dispatch(ForwardIter first, ForwardIter last,
const T& value, forward_iterator_tag, Compared comp)
{
auto len = mystl::distance(first, last);
auto half = len;
ForwardIter middle, left, right;
while (len > 0)
{
half = len >> 1;
middle = first;
mystl::advance(middle, half);
if (comp(*middle, value))
{
first = middle;
++first;
len = len - half - 1;
}
else if (comp(value, *middle))
{
len = half;
}
else
{
left = mystl::lower_bound(first, last, value, comp);
mystl::advance(first, len);
right = mystl::upper_bound(++middle, first, value, comp);
return mystl::pair(left, right);
}
}
return mystl::pair(last, last);
}
// erange_dispatch 的 random access iterator 版本
template
mystl::pair
erange_dispatch(RandomIter first, RandomIter last,
const T& value, random_access_iterator_tag, Compared comp)
{
auto len = last - first;
auto half = len;
RandomIter middle, left, right;
while (len > 0)
{
half = len >> 1;
middle = first + half;
if (comp(*middle, value))
{
first = middle + 1;
len = len - half - 1;
}
else if (comp(value, *middle))
{
len = half;
}
else
{
left = mystl::lower_bound(first, middle, value, comp);
right = mystl::upper_bound(++middle, first + len, value, comp);
return mystl::pair(left, right);
}
}
return mystl::pair(last, last);
}
template
mystl::pair
equal_range(ForwardIter first, ForwardIter last, const T& value, Compared comp)
{
return mystl::erange_dispatch(first, last, value, iterator_category(first), comp);
}
/*****************************************************************************************/
// generate
// 将函数对象 gen 的运算结果对[first, last)内的每个元素赋值
/*****************************************************************************************/
template
void generate(ForwardIter first, ForwardIter last, Generator gen)
{
for (; first != last; ++first)
{
*first = gen();
}
}
/*****************************************************************************************/
// generate_n
// 用函数对象 gen 连续对 n 个元素赋值
/*****************************************************************************************/
template
void generate_n(ForwardIter first, Size n, Generator gen)
{
for (; n > 0; --n, ++first)
{
*first = gen();
}
}
/*****************************************************************************************/
// includes
// 判断序列一S1 是否包含序列二S2
/*****************************************************************************************/
template
bool includes(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2)
{
while (first1 != last1 && first2 != last2)
{
if (*first2 < *first1)
{
return false;
}
else if (*first1 < *first2)
{
++first1;
}
else
{
++first1, ++first2;
}
}
return first2 == last2;
}
// 重载版本使用函数对象 comp 代替比较操作
template
bool includes(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2, Compared comp)
{
while (first1 != last1 && first2 != last2)
{
if (comp(*first2, *first1))
{
return false;
}
else if (comp(*first1, *first2))
{
++first1;
}
else
{
++first1, ++first2;
}
}
return first2 == last2;
}
/*****************************************************************************************/
// is_heap
// 检查[first, last)内的元素是否为一个堆,如果是,则返回 true
/*****************************************************************************************/
template
bool is_heap(RandomIter first, RandomIter last)
{
auto n = mystl::distance(first, last);
auto parent = 0;
for (auto child = 1; child < n; ++child)
{
if (first[parent] < first[child])
return false;
if ((child & 1) == 0)
++parent;
}
return true;
}
// 重载版本使用函数对象 comp 代替比较操作
template
bool is_heap(RandomIter first, RandomIter last, Compared comp)
{
auto n = mystl::distance(first, last);
auto parent = 0;
for (auto child = 1; child < n; ++child)
{
if (comp(first[parent], first[child]))
return false;
if ((child & 1) == 0)
++parent;
}
return true;
}
/*****************************************************************************************/
// is_sorted
// 检查[first, last)内的元素是否升序,如果是升序,则返回 true
/*****************************************************************************************/
template
bool is_sorted(ForwardIter first, ForwardIter last)
{
if (first == last)
return true;
auto next = first;
++next;
for (; next != last; first = next, ++next)
{
if (*next < *first)
return false;
}
return true;
}
// 重载版本使用函数对象 comp 代替比较操作
template
bool is_sorted(ForwardIter first, ForwardIter last, Compared comp)
{
if (first == last)
return true;
auto next = first;
++next;
for (; next != last; first = next, ++next)
{
if (comp(*next, *first))
return false;
}
return true;
}
/*****************************************************************************************/
// median
// 找出三个值的中间值
/*****************************************************************************************/
template
const T& median(const T& left, const T& mid, const T& right)
{
if (left < mid)
if (mid < right) // left < mid < right
return mid;
else if (left < right) // left < right <= mid
return right;
else // right <= left < mid
return left;
else if (left < right) // mid <= left < right
return left;
else if (mid < right) // mid < right <= left
return right;
else // right <= mid <= left
return mid;
}
// 重载版本使用函数对象 comp 代替比较操作
template
const T& median(const T& left, const T& mid, const T& right, Compared comp)
{
if (comp(left, mid))
if (comp(mid, right))
return mid;
else if (comp(left, right))
return right;
else
return left;
else if (comp(left, right))
return left;
else if (comp(mid, right))
return right;
else
return mid;
}
/*****************************************************************************************/
// max_element
// 返回一个迭代器,指向序列中最大的元素
/*****************************************************************************************/
template
ForwardIter max_element(ForwardIter first, ForwardIter last)
{
if (first == last)
return first;
auto result = first;
while (++first != last)
{
if (*result < *first)
result = first;
}
return result;
}
// 重载版本使用函数对象 comp 代替比较操作
template
ForwardIter max_element(ForwardIter first, ForwardIter last, Compared comp)
{
if (first == last)
return first;
auto result = first;
while (++first != last)
{
if (comp(*result, *first))
result = first;
}
return result;
}
/*****************************************************************************************/
// min_element
// 返回一个迭代器,指向序列中最小的元素
/*****************************************************************************************/
template
ForwardIter min_elememt(ForwardIter first, ForwardIter last)
{
if (first == last)
return first;
auto result = first;
while (++first != last)
{
if (*first < *result)
result = first;
}
return result;
}
// 重载版本使用函数对象 comp 代替比较操作
template
ForwardIter min_elememt(ForwardIter first, ForwardIter last, Compared comp)
{
if (first == last)
return first;
auto result = first;
while (++first != last)
{
if (comp(*first, *result))
result = first;
}
return result;
}
/*****************************************************************************************/
// swap_ranges
// 将[first1, last1)从 first2 开始,交换相同个数元素
// 交换的区间长度必须相同,两个序列不能互相重叠,返回一个迭代器指向序列二最后一个被交换元素的下一位置
/*****************************************************************************************/
template
ForwardIter2
swap_ranges(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2)
{
for (; first1 != last1; ++first1, ++first2)
{
mystl::iter_swap(first1, first2);
}
return first2;
}
/*****************************************************************************************/
// transform
// 第一个版本以函数对象 unary_op 作用于[first, last)中的每个元素并将结果保存至 result 中
// 第二个版本以函数对象 binary_op 作用于两个序列[first1, last1)、[first2, last2)的相同位置
/*****************************************************************************************/
template
OutputIter
transform(InputIter first, InputIter last,
OutputIter result, UnaryOperation unary_op)
{
for (; first != last; ++first, ++result)
{
*result = unary_op(*first);
}
return result;
}
template
OutputIter
transform(InputIter1 first1, InputIter1 last1,
InputIter2 first2, OutputIter result, BinaryOperation binary_op)
{
for (; first1 != last1; ++first1, ++first2, ++result)
{
*result = binary_op(*first1, *first2);
}
return result;
}
/*****************************************************************************************/
// remove_copy
// 移除区间内与指定 value 相等的元素,并将结果复制到以 result 标示起始位置的容器上
/*****************************************************************************************/
template
OutputIter
remove_copy(InputIter first, InputIter last, OutputIter result, const T& value)
{
for (; first != last; ++first)
{
if (*first != value)
{
*result++ = *first;
}
}
return result;
}
/*****************************************************************************************/
// remove
// 移除所有与指定 value 相等的元素
// 并不从容器中删除这些元素,所以 remove 和 remove_if 不适用于 array
/*****************************************************************************************/
template
ForwardIter remove(ForwardIter first, ForwardIter last, const T& value)
{
first = mystl::find(first, last, value); // 利用 find 找出第一个匹配的地方
auto next = first;
return first == last ? first : mystl::remove_copy(++next, last, first, value);
}
/*****************************************************************************************/
// remove_copy_if
// 移除区间内所有令一元操作 unary_pred 为 true 的元素,并将结果复制到以 result 为起始位置的容器上
/*****************************************************************************************/
template
OutputIter
remove_copy_if(InputIter first, InputIter last,
OutputIter result, UnaryPredicate unary_pred)
{
for (; first != last; ++first)
{
if (!unary_pred(*first))
{
*result = *first;
++result;
}
}
return result;
}
/*****************************************************************************************/
// remove_if
// 移除区间内所有令一元操作 unary_pred 为 true 的元素
/*****************************************************************************************/
template
ForwardIter
remove_if(ForwardIter first, ForwardIter last, UnaryPredicate unary_pred)
{
first = mystl::find_if(first, last, unary_pred); // 利用 find_if 找出第一个匹配的地方
auto next = first;
return first == last ? first : mystl::remove_copy_if(++next, last, first, unary_pred);
}
/*****************************************************************************************/
// replace
// 将区间内所有的 old_value 都以 new_value 替代
/*****************************************************************************************/
template
void replace(ForwardIter first, ForwardIter last,
const T& old_value, const T& new_value)
{
for (; first != last; ++first)
{
if (*first == old_value)
*first = new_value;
}
}
/*****************************************************************************************/
// replace_copy
// 行为与 replace 类似,不同的是将结果复制到 result 所指的容器中,原序列没有改变
/*****************************************************************************************/
template
OutputIter
replace_copy(InputIter first, InputIter last,
OutputIter result, const T& old_value, const T& new_value)
{
for (; first != last; ++first, ++result)
{
*result = *first == old_value ? new_value : *first;
}
return result;
}
/*****************************************************************************************/
// replace_copy_if
// 行为与 replace_if 类似,不同的是将结果复制到 result 所指的容器中,原序列没有改变
/*****************************************************************************************/
template
OutputIter
replace_copy_if(InputIter first, InputIter last,
OutputIter result, UnaryPredicate unary_pred, const T& new_value)
{
for (; first != last; ++first, ++result)
{
*result = unary_pred(*first) ? new_value : *first;
}
return result;
}
/*****************************************************************************************/
// replace_if
// 将区间内所有令一元操作 unary_pred 为 true 的元素都用 new_value 替代
/*****************************************************************************************/
template
void replace_if(ForwardIter first, ForwardIter last,
UnaryPredicate unary_pred, const T& new_value)
{
for (; first != last; ++first)
{
if (unary_pred(*first))
*first = new_value;
}
}
/*****************************************************************************************/
// reverse
// 将[first, last)区间内的元素反转
/*****************************************************************************************/
// reverse_dispatch 的 bidirectional_iterator_tag 版本
template
void reverse_dispatch(BidirectionalIter first, BidirectionalIter last,
bidirectional_iterator_tag)
{
while (true)
{
if (first == last || first == --last)
return;
mystl::iter_swap(first++, last);
}
}
// reverse_dispatch 的 random_access_iterator_tag 版本
template
void reverse_dispatch(RandomIter first, RandomIter last,
random_access_iterator_tag)
{
while (first < last)
mystl::iter_swap(first++, --last);
}
template
void reverse(BidirectionalIter first, BidirectionalIter last)
{
mystl::reverse_dispatch(first, last, iterator_category(first));
}
/*****************************************************************************************/
// reverse_copy
// 行为与 reverse 类似,不同的是将结果复制到 result 所指容器中
/*****************************************************************************************/
template
OutputIter
reverse_copy(BidirectionalIter first, BidirectionalIter last,
OutputIter result)
{
while (first != last)
{
--last;
*result = *last;
++result;
}
return result;
}
/*****************************************************************************************/
// random_shuffle
// 将[first, last)内的元素次序随机重排
// 重载版本使用一个产生随机数的函数对象 rand
/*****************************************************************************************/
template
void random_shuffle(RandomIter first, RandomIter last)
{
if (first == last)
return;
srand((unsigned)time(0));
for (auto i = first + 1; i != last; ++i)
{
mystl::iter_swap(i, first + (rand() % (i - first + 1)));
}
}
// 重载版本使用一个产生随机数的函数对象 rand
template
void random_shuffle(RandomIter first, RandomIter last,
RandomNumberGenerator& rand)
{
if (first == last)
return;
auto len = mystl::distance(first, last);
for (auto i = first + 1; i != last; ++i)
{
mystl::iter_swap(i, first + (rand(i - first + 1) % len));
}
}
/*****************************************************************************************/
// rotate
// 将[first, middle)内的元素和 [middle, last)内的元素互换,可以交换两个长度不同的区间
// 返回交换后 middle 的位置
/*****************************************************************************************/
// rotate_dispatch 的 forward_iterator_tag 版本
template
ForwardIter
rotate_dispatch(ForwardIter first, ForwardIter middle,
ForwardIter last, forward_iterator_tag)
{
auto first2 = middle;
do
{
mystl::swap(*first++, *first2++);
if (first == middle)
middle = first2;
} while (first2 != last); // 后半段移到前面
auto new_middle = first; // 迭代器返回的位置
first2 = middle;
while (first2 != last)
{ // 调整剩余元素
mystl::swap(*first++, *first2++);
if (first == middle)
{
middle = first2;
}
else if (first2 == last)
{
first2 = middle;
}
}
return new_middle;
}
// rotate_dispatch 的 bidirectional_iterator_tag 版本
template
BidirectionalIter
rotate_dispatch(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last, bidirectional_iterator_tag)
{
mystl::reverse_dispatch(first, middle, bidirectional_iterator_tag());
mystl::reverse_dispatch(middle, last, bidirectional_iterator_tag());
while (first != middle && middle != last)
mystl::swap(*first++, *--last);
if (first == middle)
{
mystl::reverse_dispatch(middle, last, bidirectional_iterator_tag());
return last;
}
else
{
mystl::reverse_dispatch(first, middle, bidirectional_iterator_tag());
return first;
}
}
// 求最大公因子
template
EuclideanRingElement rgcd(EuclideanRingElement m, EuclideanRingElement n)
{
while (n != 0)
{
auto t = m % n;
m = n;
n = t;
}
return m;
}
// rotate_dispatch 的 random_access_iterator_tag 版本
template
RandomIter
rotate_dispatch(RandomIter first, RandomIter middle,
RandomIter last, random_access_iterator_tag)
{
// 因为是 random access iterator,我们可以确定每个元素的位置
auto n = last - first;
auto l = middle - first;
auto r = n - l;
auto result = first + (last - middle);
if (l == r)
{
mystl::swap_ranges(first, middle, middle);
return result;
}
auto cycle_times = rgcd(n, l);
for (auto i = 0; i < cycle_times; ++i)
{
auto tmp = *first;
auto p = first;
if (l < r)
{
for (auto j = 0; j < r / cycle_times; ++j)
{
if (p > first + r)
{
*p = *(p - r);
p -= r;
}
*p = *(p + l);
p += l;
}
}
else
{
for (auto j = 0; j < l / cycle_times - 1; ++j)
{
if (p < last - l)
{
*p = *(p + l);
p += l;
}
*p = *(p - r);
p -= r;
}
}
*p = tmp;
++first;
}
return result;
}
template
ForwardIter
rotate(ForwardIter first, ForwardIter middle, ForwardIter last)
{
if (first == middle)
return last;
if (middle == last)
return first;
return mystl::rotate_dispatch(first, middle, last, iterator_category(first));
}
/*****************************************************************************************/
// rotate_copy
// 行为与 rotate 类似,不同的是将结果复制到 result 所指的容器中
/*****************************************************************************************/
template
ForwardIter
rotate_copy(ForwardIter first, ForwardIter middle,
ForwardIter last, OutputIter result)
{
return mystl::copy(first, middle, mystl::copy(middle, last, result));
}
/*****************************************************************************************/
// is_permutation
// 判断[first1,last1)是否为[first2, last2)的排列组合
/*****************************************************************************************/
template
bool is_permutation_aux(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
BinaryPred pred)
{
constexpr bool is_ra_it = mystl::is_random_access_iterator::value
&& mystl::is_random_access_iterator::value;
if (is_ra_it)
{
auto len1 = last1 - first1;
auto len2 = last2 - first2;
if (len1 != len2)
return false;
}
// 先找出相同的前缀段
for (; first1 != last1 && first2 != last2; ++first1, (void) ++first2)
{
if (!pred(*first1, *first2))
break;
}
if (is_ra_it)
{
if (first1 == last1)
return true;
}
else
{
auto len1 = mystl::distance(first1, last1);
auto len2 = mystl::distance(first2, last2);
if (len1 == 0 && len2 == 0)
return true;
if (len1 != len2)
return false;
}
// 判断剩余部分
for (auto i = first1; i != last1; ++i)
{
bool is_repeated = false;
for (auto j = first1; j != i; ++j)
{
if (pred(*j, *i))
{
is_repeated = true;
break;
}
}
if (!is_repeated)
{
// 计算 *i 在 [first2, last2) 的数目
auto c2 = 0;
for (auto j = first2; j != last2; ++j)
{
if (pred(*i, *j))
++c2;
}
if (c2 == 0)
return false;
// 计算 *i 在 [first1, last1) 的数目
auto c1 = 1;
auto j = i;
for (++j; j != last1; ++j)
{
if (pred(*i, *j))
++c1;
}
if (c1 != c2)
return false;
}
}
return true;
}
template
bool is_permutation(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
BinaryPred pred)
{
return is_permutation_aux(first1, last1, first2, last2, pred);
}
template
bool is_permutation(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2)
{
typedef typename iterator_traits::value_type v1;
typedef typename iterator_traits::value_type v2;
static_assert(std::is_same::value,
"the type should be same in mystl::is_permutation");
return is_permutation_aux(first1, last1, first2, last2,
mystl::equal_to());
}
/*****************************************************************************************/
// next_permutation
// 取得[first, last)所标示序列的下一个排列组合,如果没有下一个排序组合,返回 false,否则返回 true
/*****************************************************************************************/
template
bool next_permutation(BidirectionalIter first, BidirectionalIter last)
{
auto i = last;
if (first == last || first == --i)
return false;
for (;;)
{
auto ii = i;
if (*--i < *ii)
{ // 找到第一对小于关系的元素
auto j = last;
while (!(*i < *--j)) {}
mystl::iter_swap(i, j); // 交换 i,j 所指元素
mystl::reverse(ii, last); // 将 ii 之后的所有元素反转
return true;
}
if (i == first)
{
mystl::reverse(first, last);
return false;
}
}
}
// 重载版本使用函数对象 comp 代替比较操作
template
bool next_permutation(BidirectionalIter first, BidirectionalIter last, Compared comp)
{
auto i = last;
if (first == last || first == --i)
return false;
for (;;)
{
auto ii = i;
if (comp(*--i, *ii))
{
auto j = last;
while (!comp(*i, *--j)) {}
mystl::iter_swap(i, j); // 交换 i,j 所指元素
mystl::reverse(ii, last); // 将 ii 之后的所有元素反转
return true;
}
if (i == first)
{
mystl::reverse(first, last);
return false;
}
}
}
/*****************************************************************************************/
// prev_permutation
// 取得[first, last)所标示序列的上一个排列组合,如果没有上一个排序组合,返回 false,否则返回 true
/*****************************************************************************************/
template
bool prev_permutation(BidirectionalIter first, BidirectionalIter last)
{
auto i = last;
if (first == last || first == --i)
return false;
for (;;)
{
auto ii = i;
if (*ii < *--i)
{ // 找到第一对大于关系的元素
auto j = last;
while (!(*--j < *i)) {}
mystl::iter_swap(i, j); // 交换i,j
mystl::reverse(ii, last); // 将 ii 之后的所有元素反转
return true;
}
if (i == first)
{
mystl::reverse(first, last);
return false;
}
}
}
// 重载版本使用函数对象 comp 代替比较操作
template
bool prev_permutation(BidirectionalIter first, BidirectionalIter last, Compared comp)
{
auto i = last;
if (first == last || first == --i)
return false;
for (;;)
{
auto ii = i;
if (comp(*ii, *--i))
{
auto j = last;
while (!comp(*--j, *i)) {}
mystl::iter_swap(i, j); // 交换i,j
mystl::reverse(ii, last); // 将 ii 之后的所有元素反转
return true;
}
if (i == first)
{
mystl::reverse(first, last);
return false;
}
}
}
/*****************************************************************************************/
// merge
// 将两个经过排序的集合 S1 和 S2 合并起来置于另一段空间,返回一个迭代器指向最后一个元素的下一位置
/*****************************************************************************************/
template
OutputIter
merge(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result)
{
while (first1 != last1 && first2 != last2)
{
if (*first2 < *first1)
{
*result = *first2;
++first2;
}
else
{
*result = *first1;
++first1;
}
++result;
}
return mystl::copy(first2, last2, mystl::copy(first1, last1, result));
}
// 重载版本使用函数对象 comp 代替比较操作
template
OutputIter
merge(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result, Compared comp)
{
while (first1 != last1 && first2 != last2)
{
if (comp(*first2, *first1))
{
*result = *first2;
++first2;
}
else
{
*result = *first1;
++first1;
}
++result;
}
return mystl::copy(first2, last2, mystl::copy(first1, last1, result));
}
/*****************************************************************************************/
// inplace_merge
// 把连接在一起的两个有序序列结合成单一序列并保持有序
/*****************************************************************************************/
// 没有缓冲区的情况下合并
template
void merge_without_buffer(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last, Distance len1, Distance len2)
{
if (len1 == 0 || len2 == 0)
return;
if (len1 + len2 == 2)
{
if (*middle < *first)
mystl::iter_swap(first, middle);
return;
}
auto first_cut = first;
auto second_cut = middle;
Distance len11 = 0;
Distance len22 = 0;
if (len1 > len2)
{ // 序列一较长,找到序列一的中点
len11 = len1 >> 1;
mystl::advance(first_cut, len11);
second_cut = mystl::lower_bound(middle, last, *first_cut);
len22 = mystl::distance(middle, second_cut);
}
else
{ // 序列二较长,找到序列二的中点
len22 = len2 >> 1;
mystl::advance(second_cut, len22);
first_cut = mystl::upper_bound(first, middle, *second_cut);
len11 = mystl::distance(first, first_cut);
}
auto new_middle = mystl::rotate(first_cut, middle, second_cut);
mystl::merge_without_buffer(first, first_cut, new_middle, len11, len22);
mystl::merge_without_buffer(new_middle, second_cut, last, len1 - len11, len2 - len22);
}
template
BidirectionalIter1
merge_backward(BidirectionalIter1 first1, BidirectionalIter1 last1,
BidirectionalIter2 first2, BidirectionalIter2 last2,
BidirectionalIter1 result)
{
if (first1 == last1)
return mystl::copy_backward(first2, last2, result);
if (first2 == last2)
return mystl::copy_backward(first1, last1, result);
--last1;
--last2;
while (true)
{
if (*last2 < *last1)
{
*--result = *last1;
if (first1 == last1)
return mystl::copy_backward(first2, ++last2, result);
--last1;
}
else
{
*--result = *last2;
if (first2 == last2)
return mystl::copy_backward(first1, ++last1, result);
--last2;
}
}
}
template
BidirectionalIter1
rotate_adaptive(BidirectionalIter1 first, BidirectionalIter1 middle,
BidirectionalIter1 last, Distance len1, Distance len2,
BidirectionalIter2 buffer, Distance buffer_size)
{
BidirectionalIter2 buffer_end;
if (len1 > len2 && len2 <= buffer_size)
{
buffer_end = mystl::copy(middle, last, buffer);
mystl::copy_backward(first, middle, last);
return mystl::copy(buffer, buffer_end, first);
}
else if (len1 <= buffer_size)
{
buffer_end = mystl::copy(first, middle, buffer);
mystl::copy(middle, last, first);
return mystl::copy_backward(buffer, buffer_end, last);
}
else
{
return mystl::rotate(first, middle, last);
}
}
// 有缓冲区的情况下合并
template
void merge_adaptive(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last, Distance len1, Distance len2,
Pointer buffer, Distance buffer_size)
{
// 区间长度足够放进缓冲区
if (len1 <= len2 && len1 <= buffer_size)
{
Pointer buffer_end = mystl::copy(first, middle, buffer);
mystl::merge(buffer, buffer_end, middle, last, first);
}
else if (len2 <= buffer_size)
{
Pointer buffer_end = mystl::copy(middle, last, buffer);
mystl::merge_backward(first, middle, buffer, buffer_end, last);
}
else
{ // 区间长度太长,分割递归处理
auto first_cut = first;
auto second_cut = middle;
Distance len11 = 0;
Distance len22 = 0;
if (len1 > len2)
{
len11 = len1 >> 1;
mystl::advance(first_cut, len11);
second_cut = mystl::lower_bound(middle, last, *first_cut);
len22 = mystl::distance(middle, second_cut);
}
else
{
len22 = len2 >> 1;
mystl::advance(second_cut, len22);
first_cut = mystl::upper_bound(first, middle, *second_cut);
len11 = mystl::distance(first, first_cut);
}
auto new_middle = mystl::rotate_adaptive(first_cut, middle, second_cut,
len1 - len11, len22, buffer, buffer_size);
mystl::merge_adaptive(first, first_cut, new_middle, len11, len22, buffer, buffer_size);
mystl::merge_adaptive(new_middle, second_cut, last, len1 - len11,
len2 - len22, buffer, buffer_size);
}
}
template
void
inplace_merge_aux(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last, T*)
{
auto len1 = mystl::distance(first, middle);
auto len2 = mystl::distance(middle, last);
temporary_buffer buf(first, last);
if (!buf.begin())
{
mystl::merge_without_buffer(first, middle, last, len1, len2);
}
else
{
mystl::merge_adaptive(first, middle, last, len1, len2, buf.begin(), buf.size());
}
}
template
void
inplace_merge(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last)
{
if (first == middle || middle == last)
return;
mystl::inplace_merge_aux(first, middle, last, value_type(first));
}
// 重载版本使用函数对象 comp 代替比较操作
// 没有缓冲区的情况下合并
template
void merge_without_buffer(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last, Distance len1, Distance len2,
Compared comp)
{
if (len1 == 0 || len2 == 0)
return;
if (len1 + len2 == 2)
{
if (comp(*middle, *first))
mystl::iter_swap(first, middle);
return;
}
auto first_cut = first;
auto second_cut = middle;
Distance len11 = 0;
Distance len22 = 0;
if (len1 > len2)
{
len11 = len1 >> 1;
mystl::advance(first_cut, len11);
second_cut = mystl::lower_bound(middle, last, *first_cut, comp);
len22 = mystl::distance(middle, second_cut);
}
else
{
len22 = len2 >> 1;
mystl::advance(second_cut, len22);
first_cut = mystl::upper_bound(first, middle, *second_cut, comp);
len11 = mystl::distance(first, first_cut);
}
auto new_middle = mystl::rotate(first_cut, middle, second_cut);
mystl::merge_without_buffer(first, first_cut, new_middle, len11, len22, comp);
mystl::merge_without_buffer(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
}
template
BidirectionalIter1
merge_backward(BidirectionalIter1 first1, BidirectionalIter1 last1,
BidirectionalIter2 first2, BidirectionalIter2 last2,
BidirectionalIter1 result, Compared comp)
{
if (first1 == last1)
return mystl::copy_backward(first2, last2, result);
if (first2 == last2)
return mystl::copy_backward(first1, last1, result);
--last1;
--last2;
while (true)
{
if (comp(*last2, *last1))
{
*--result = *last1;
if (first1 == last1)
return mystl::copy_backward(first2, ++last2, result);
--last1;
}
else
{
*--result = *last2;
if (first2 == last2)
return mystl::copy_backward(first1, ++last1, result);
--last2;
}
}
}
// 有缓冲区的情况下合并
template
void merge_adaptive(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last, Distance len1, Distance len2,
Pointer buffer, Distance buffer_size, Compared comp)
{
// 区间长度足够放进缓冲区
if (len1 <= len2 && len1 <= buffer_size)
{
Pointer buffer_end = mystl::copy(first, middle, buffer);
mystl::merge(buffer, buffer_end, middle, last, first, comp);
}
else if (len2 <= buffer_size)
{
Pointer buffer_end = mystl::copy(middle, last, buffer);
mystl::merge_backward(first, middle, buffer, buffer_end, last, comp);
}
else
{ // 区间长度太长,分割递归处理
auto first_cut = first;
auto second_cut = middle;
Distance len11 = 0;
Distance len22 = 0;
if (len1 > len2)
{
len11 = len1 >> 1;
mystl::advance(first_cut, len11);
second_cut = mystl::lower_bound(middle, last, *first_cut, comp);
len22 = mystl::distance(middle, second_cut);
}
else
{
len22 = len2 >> 1;
mystl::advance(second_cut, len22);
first_cut = mystl::upper_bound(first, middle, *second_cut, comp);
len11 = mystl::distance(first, first_cut);
}
auto new_middle = mystl::rotate_adaptive(first_cut, middle, second_cut, len1 - len11,
len22, buffer, buffer_size);
mystl::merge_adaptive(first, first_cut, new_middle, len11,
len22, buffer, buffer_size, comp);
mystl::merge_adaptive(new_middle, second_cut, last, len1 - len11,
len2 - len22, buffer, buffer_size, comp);
}
}
template
void
inplace_merge_aux(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last, T*, Compared comp)
{
auto len1 = mystl::distance(first, middle);
auto len2 = mystl::distance(middle, last);
temporary_buffer buf(first, last);
if (!buf.begin())
{
mystl::merge_without_buffer(first, middle, last, len1, len2, comp);
}
else
{
mystl::merge_adaptive(first, middle, last, len1, len2, buf.begin(), buf.size(), comp);
}
}
template
void
inplace_merge(BidirectionalIter first, BidirectionalIter middle,
BidirectionalIter last, Compared comp)
{
if (first == middle || middle == last)
return;
mystl::inplace_merge_aux(first, middle, last, value_type(first), comp);
}
/*****************************************************************************************/
// partial_sort
// 对整个序列做部分排序,保证较小的 N 个元素以递增顺序置于[first, first + N)中
/*****************************************************************************************/
template
void partial_sort(RandomIter first, RandomIter middle,
RandomIter last)
{
mystl::make_heap(first, middle);
for (auto i = middle; i < last; ++i)
{
if (*i < *first)
{
mystl::pop_heap_aux(first, middle, i, *i, distance_type(first));
}
}
mystl::sort_heap(first, middle);
}
// 重载版本使用函数对象 comp 代替比较操作
template
void partial_sort(RandomIter first, RandomIter middle,
RandomIter last, Compared comp)
{
mystl::make_heap(first, middle, comp);
for (auto i = middle; i < last; ++i)
{
if (comp(*i, *first))
{
mystl::pop_heap_aux(first, middle, i, *i, distance_type(first), comp);
}
}
mystl::sort_heap(first, middle, comp);
}
/*****************************************************************************************/
// partial_sort_copy
// 行为与 partial_sort 类似,不同的是把排序结果复制到 result 容器中
/*****************************************************************************************/
template
RandomIter
psort_copy_aux(InputIter first, InputIter last,
RandomIter result_first, RandomIter result_last,
Distance*)
{
if (result_first == result_last)
return result_last;
auto result_iter = result_first;
while (first != last && result_iter != result_last)
{
*result_iter = *first;
++result_iter;
++first;
}
mystl::make_heap(result_first, result_iter);
while (first != last)
{
if (*first < *result_first)
{
mystl::adjust_heap(result_first, static_cast(0),
result_iter - result_first, *first);
}
++first;
}
mystl::sort_heap(result_first, result_iter);
return result_iter;
}
template
RandomIter
partial_sort_copy(InputIter first, InputIter last,
RandomIter result_first, RandomIter result_last)
{
return mystl::psort_copy_aux(first, last, result_first, result_last,
distance_type(result_first));
}
// 重载版本使用函数对象 comp 代替比较操作
template
RandomIter
psort_copy_aux(InputIter first, InputIter last,
RandomIter result_first, RandomIter result_last,
Distance*, Compared comp)
{
if (result_first == result_last)
return result_last;
auto result_iter = result_first;
while (first != last && result_iter != result_last)
{
*result_iter = *first;
++result_iter;
++first;
}
mystl::make_heap(result_first, result_iter, comp);
while (first != last)
{
if (comp(*first, *result_first))
{
mystl::adjust_heap(result_first, static_cast(0),
result_iter - result_first, *first, comp);
}
++first;
}
mystl::sort_heap(result_first, result_iter, comp);
return result_iter;
}
template
RandomIter
partial_sort_copy(InputIter first, InputIter last,
RandomIter result_first, RandomIter result_last,
Compared comp)
{
return mystl::psort_copy_aux(first, last, result_first, result_last,
distance_type(result_first), comp);
}
/*****************************************************************************************/
// partition
// 对区间内的元素重排,被一元条件运算判定为 true 的元素会放到区间的前段
// 该函数不保证元素的原始相对位置
/*****************************************************************************************/
template
BidirectionalIter
partition(BidirectionalIter first, BidirectionalIter last,
UnaryPredicate unary_pred)
{
while (true)
{
while (first != last && unary_pred(*first))
{
++first;
}
if (first == last)
break;
--last;
while (first != last && !unary_pred(*last))
{
--last;
}
if (first == last)
break;
mystl::iter_swap(first, last);
++first;
}
return first;
}
/*****************************************************************************************/
// partition_copy
// 行为与 partition 类似,不同的是,将被一元操作符判定为 true 的放到 result_true 的输出区间
// 其余放到 result_false 的输出区间,并返回一个 mystl::pair 指向这两个区间的尾部
/*****************************************************************************************/
template
mystl::pair
partition_copy(InputIter first, InputIter last,
OutputIter1 result_true, OutputIter2 result_false,
UnaryPredicate unary_pred)
{
for (; first != last; ++first)
{
if (unary_pred(*first))
{
*result_true++ = *first;
}
else
{
*result_false++ = *first;
}
}
return mystl::pair(result_true, result_false);
}
/*****************************************************************************************/
// sort
// 将[first, last)内的元素以递增的方式排序
/*****************************************************************************************/
constexpr static size_t kSmallSectionSize = 128; // 小型区间的大小,在这个大小内采用插入排序
// 用于控制分割恶化的情况
template
Size slg2(Size n)
{ // 找出 lgk <= n 的 k 的最大值
Size k = 0;
for (; n > 1; n >>= 1)
++k;
return k;
}
// 分割函数 unchecked_partition
template
RandomIter
unchecked_partition(RandomIter first, RandomIter last, const T& pivot)
{
while (true)
{
while (*first < pivot)
++first;
--last;
while (pivot < *last)
--last;
if (!(first < last))
return first;
mystl::iter_swap(first, last);
++first;
}
}
// 内省式排序,先进行 quick sort,当分割行为有恶化倾向时,改用 heap sort
template
void intro_sort(RandomIter first, RandomIter last, Size depth_limit)
{
while (static_cast(last - first) > kSmallSectionSize)
{
if (depth_limit == 0)
{ // 到达最大分割深度限制
mystl::partial_sort(first, last, last); // 改用 heap_sort
return;
}
--depth_limit;
auto mid = mystl::median(*(first), *(first + (last - first) / 2), *(last - 1));
auto cut = mystl::unchecked_partition(first, last, mid);
mystl::intro_sort(cut, last, depth_limit);
last = cut;
}
}
// 插入排序辅助函数 unchecked_linear_insert
template
void unchecked_linear_insert(RandomIter last, const T& value)
{
auto next = last;
--next;
while (value < *next)
{
*last = *next;
last = next;
--next;
}
*last = value;
}
// 插入排序函数 unchecked_insertion_sort
template
void unchecked_insertion_sort(RandomIter first, RandomIter last)
{
for (auto i = first; i != last; ++i)
{
mystl::unchecked_linear_insert(i, *i);
}
}
// 插入排序函数 insertion_sort
template
void insertion_sort(RandomIter first, RandomIter last)
{
if (first == last)
return;
for (auto i = first + 1; i != last; ++i)
{
auto value = *i;
if (value < *first)
{
mystl::copy_backward(first, i, i + 1);
*first = value;
}
else
{
mystl::unchecked_linear_insert(i, value);
}
}
}
// 最终插入排序函数 final_insertion_sort
template
void final_insertion_sort(RandomIter first, RandomIter last)
{
if (static_cast(last - first) > kSmallSectionSize)
{
mystl::insertion_sort(first, first + kSmallSectionSize);
mystl::unchecked_insertion_sort(first + kSmallSectionSize, last);
}
else
{
mystl::insertion_sort(first, last);
}
}
template
void sort(RandomIter first, RandomIter last)
{
if (first != last)
{
// 内省式排序,将区间分为一个个小区间,然后对整体进行插入排序
mystl::intro_sort(first, last, slg2(last - first) * 2);
mystl::final_insertion_sort(first, last);
}
}
// 重载版本使用函数对象 comp 代替比较操作
// 分割函数 unchecked_partition
template
RandomIter
unchecked_partition(RandomIter first, RandomIter last,
const T& pivot, Compared comp)
{
while (true)
{
while (comp(*first, pivot))
++first;
--last;
while (comp(pivot, *last))
--last;
if (!(first < last))
return first;
mystl::iter_swap(first, last);
++first;
}
}
// 内省式排序,先进行 quick sort,当分割行为有恶化倾向时,改用 heap sort
template
void intro_sort(RandomIter first, RandomIter last,
Size depth_limit, Compared comp)
{
while (static_cast(last - first) > kSmallSectionSize)
{
if (depth_limit == 0)
{ // 到达最大分割深度限制
mystl::partial_sort(first, last, last, comp); // 改用 heap_sort
return;
}
--depth_limit;
auto mid = mystl::median(*(first), *(first + (last - first) / 2), *(last - 1));
auto cut = mystl::unchecked_partition(first, last, mid, comp);
mystl::intro_sort(cut, last, depth_limit, comp);
last = cut;
}
}
// 插入排序辅助函数 unchecked_linear_insert
template
void unchecked_linear_insert(RandomIter last, const T& value, Compared comp)
{
auto next = last;
--next;
while (comp(value, *next))
{ // 从尾部开始寻找第一个可插入位置
*last = *next;
last = next;
--next;
}
*last = value;
}
// 插入排序函数 unchecked_insertion_sort
template
void unchecked_insertion_sort(RandomIter first, RandomIter last,
Compared comp)
{
for (auto i = first; i != last; ++i)
{
mystl::unchecked_linear_insert(i, *i, comp);
}
}
// 插入排序函数 insertion_sort
template
void insertion_sort(RandomIter first, RandomIter last, Compared comp)
{
if (first == last)
return;
for (auto i = first + 1; i != last; ++i)
{
auto value = *i;
if (comp(value, *first))
{
mystl::copy_backward(first, i, i + 1);
*first = value;
}
else
{
mystl::unchecked_linear_insert(i, value, comp);
}
}
}
// 最终插入排序函数 final_insertion_sort
template
void final_insertion_sort(RandomIter first, RandomIter last, Compared comp)
{
if (static_cast(last - first) > kSmallSectionSize)
{
mystl::insertion_sort(first, first + kSmallSectionSize, comp);
mystl::unchecked_insertion_sort(first + kSmallSectionSize, last, comp);
}
else
{
mystl::insertion_sort(first, last, comp);
}
}
template
void sort(RandomIter first, RandomIter last, Compared comp)
{
if (first != last)
{
// 内省式排序,将区间分为一个个小区间,然后对整体进行插入排序
mystl::intro_sort(first, last, slg2(last - first) * 2, comp);
mystl::final_insertion_sort(first, last, comp);
}
}
/*****************************************************************************************/
// nth_element
// 对序列重排,使得所有小于第 n 个元素的元素出现在它的前面,大于它的出现在它的后面
/*****************************************************************************************/
template
void nth_element(RandomIter first, RandomIter nth,
RandomIter last)
{
if (nth == last)
return;
while (last - first > 3)
{
auto cut = mystl::unchecked_partition(first, last, mystl::median(*first,
*(first + (last - first) / 2),
*(last - 1)));
if (cut <= nth) // 如果 nth 位于右段
first = cut; // 对右段进行分割
else
last = cut; // 对左段进行分割
}
mystl::insertion_sort(first, last);
}
// 重载版本使用函数对象 comp 代替比较操作
template
void nth_element(RandomIter first, RandomIter nth,
RandomIter last, Compared comp)
{
if (nth == last)
return;
while (last - first > 3)
{
auto cut = mystl::unchecked_partition(first, last, mystl::median(*first,
*(first + (last - first) / 2),
*(last - 1)), comp);
if (cut <= nth) // 如果 nth 位于右段
first = cut; // 对右段进行分割
else
last = cut; // 对左段进行分割
}
mystl::insertion_sort(first, last, comp);
}
/*****************************************************************************************/
// unique_copy
// 从[first, last)中将元素复制到 result 上,序列必须有序,如果有重复的元素,只会复制一次
/*****************************************************************************************/
// unique_copy_dispatch 的 forward_iterator_tag 版本
template
ForwardIter
unique_copy_dispatch(InputIter first, InputIter last,
ForwardIter result, forward_iterator_tag)
{
*result = *first;
while (++first != last)
{
if (*result != *first)
*++result = *first;
}
return ++result;
}
// unique_copy_dispatch 的 output_iterator_tag 版本
// 由于 output iterator 只能进行只读操作,所以不能有 *result != *first 这样的判断
template
OutputIter
unique_copy_dispatch(InputIter first, InputIter last,
OutputIter result, output_iterator_tag)
{
auto value = *first;
*result = value;
while (++first != last)
{
if (value != *first)
{
value = *first;
*++result = value;
}
}
return ++result;
}
template
OutputIter
unique_copy(InputIter first, InputIter last, OutputIter result)
{
if (first == last)
return result;
return mystl::unique_copy_dispatch(first, last, result, iterator_category(result));
}
// 重载版本使用函数对象 comp 代替比较操作
// unique_copy_dispatch 的 forward_iterator_tag 版本
template
ForwardIter
unique_copy_dispatch(InputIter first, InputIter last,
ForwardIter result, forward_iterator_tag, Compared comp)
{
*result = *first;
while (++first != last)
{
if (!comp(*result, *first))
*++result = *first;
}
return ++result;
}
// unique_copy_dispatch 的 output_iterator_tag 版本
// 由于 output iterator 只能进行只读操作,所以不能有 *result != *first 这样的判断
template
OutputIter
unique_copy_dispatch(InputIter first, InputIter last,
OutputIter result, output_iterator_tag, Compared comp)
{
auto value = *first;
*result = value;
while (++first != last)
{
if (!comp(value, *first))
{
value = *first;
*++result = value;
}
}
return ++result;
}
template
OutputIter
unique_copy(InputIter first, InputIter last, OutputIter result, Compared comp)
{
if (first == last)
return result;
return mystl::unique_copy_dispatch(first, last, result, iterator_category(result), comp);
}
/*****************************************************************************************/
// unique
// 移除[first, last)内重复的元素,序列必须有序,和 remove 类似,它也不能真正的删除重复元素
/*****************************************************************************************/
template
ForwardIter unique(ForwardIter first, ForwardIter last)
{
first = mystl::adjacent_find(first, last);
return mystl::unique_copy(first, last, first);
}
// 重载版本使用函数对象 comp 代替比较操作
template
ForwardIter unique(ForwardIter first, ForwardIter last, Compared comp)
{
first = mystl::adjacent_find(first, last, comp);
return mystl::unique_copy(first, last, first, comp);
}
} // namespace mystl
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif // !MYTINYSTL_ALGO_H_
================================================
FILE: MyTinySTL/algobase.h
================================================
#ifndef MYTINYSTL_ALGOBASE_H_
#define MYTINYSTL_ALGOBASE_H_
// 这个头文件包含了 mystl 的基本算法
#include
#include "iterator.h"
#include "util.h"
namespace mystl
{
#ifdef max
#pragma message("#undefing marco max")
#undef max
#endif // max
#ifdef min
#pragma message("#undefing marco min")
#undef min
#endif // min
/*****************************************************************************************/
// max
// 取二者中的较大值,语义相等时保证返回第一个参数
/*****************************************************************************************/
template
const T& max(const T& lhs, const T& rhs)
{
return lhs < rhs ? rhs : lhs;
}
// 重载版本使用函数对象 comp 代替比较操作
template
const T& max(const T& lhs, const T& rhs, Compare comp)
{
return comp(lhs, rhs) ? rhs : lhs;
}
/*****************************************************************************************/
// min
// 取二者中的较小值,语义相等时保证返回第一个参数
/*****************************************************************************************/
template
const T& min(const T& lhs, const T& rhs)
{
return rhs < lhs ? rhs : lhs;
}
// 重载版本使用函数对象 comp 代替比较操作
template
const T& min(const T& lhs, const T& rhs, Compare comp)
{
return comp(rhs, lhs) ? rhs : lhs;
}
/*****************************************************************************************/
// iter_swap
// 将两个迭代器所指对象对调
/*****************************************************************************************/
template
void iter_swap(FIter1 lhs, FIter2 rhs)
{
mystl::swap(*lhs, *rhs);
}
/*****************************************************************************************/
// copy
// 把 [first, last)区间内的元素拷贝到 [result, result + (last - first))内
/*****************************************************************************************/
// input_iterator_tag 版本
template
OutputIter
unchecked_copy_cat(InputIter first, InputIter last, OutputIter result,
mystl::input_iterator_tag)
{
for (; first != last; ++first, ++result)
{
*result = *first;
}
return result;
}
// ramdom_access_iterator_tag 版本
template
OutputIter
unchecked_copy_cat(RandomIter first, RandomIter last, OutputIter result,
mystl::random_access_iterator_tag)
{
for (auto n = last - first; n > 0; --n, ++first, ++result)
{
*result = *first;
}
return result;
}
template
OutputIter
unchecked_copy(InputIter first, InputIter last, OutputIter result)
{
return unchecked_copy_cat(first, last, result, iterator_category(first));
}
// 为 trivially_copy_assignable 类型提供特化版本
template
typename std::enable_if<
std::is_same::type, Up>::value &&
std::is_trivially_copy_assignable::value,
Up*>::type
unchecked_copy(Tp* first, Tp* last, Up* result)
{
const auto n = static_cast(last - first);
if (n != 0)
std::memmove(result, first, n * sizeof(Up));
return result + n;
}
template
OutputIter copy(InputIter first, InputIter last, OutputIter result)
{
return unchecked_copy(first, last, result);
}
/*****************************************************************************************/
// copy_backward
// 将 [first, last)区间内的元素拷贝到 [result - (last - first), result)内
/*****************************************************************************************/
// unchecked_copy_backward_cat 的 bidirectional_iterator_tag 版本
template
BidirectionalIter2
unchecked_copy_backward_cat(BidirectionalIter1 first, BidirectionalIter1 last,
BidirectionalIter2 result, mystl::bidirectional_iterator_tag)
{
while (first != last)
*--result = *--last;
return result;
}
// unchecked_copy_backward_cat 的 random_access_iterator_tag 版本
template
BidirectionalIter2
unchecked_copy_backward_cat(RandomIter1 first, RandomIter1 last,
BidirectionalIter2 result, mystl::random_access_iterator_tag)
{
for (auto n = last - first; n > 0; --n)
*--result = *--last;
return result;
}
template
BidirectionalIter2
unchecked_copy_backward(BidirectionalIter1 first, BidirectionalIter1 last,
BidirectionalIter2 result)
{
return unchecked_copy_backward_cat(first, last, result,
iterator_category(first));
}
// 为 trivially_copy_assignable 类型提供特化版本
template
typename std::enable_if<
std::is_same::type, Up>::value &&
std::is_trivially_copy_assignable::value,
Up*>::type
unchecked_copy_backward(Tp* first, Tp* last, Up* result)
{
const auto n = static_cast(last - first);
if (n != 0)
{
result -= n;
std::memmove(result, first, n * sizeof(Up));
}
return result;
}
template
BidirectionalIter2
copy_backward(BidirectionalIter1 first, BidirectionalIter1 last, BidirectionalIter2 result)
{
return unchecked_copy_backward(first, last, result);
}
/*****************************************************************************************/
// copy_if
// 把[first, last)内满足一元操作 unary_pred 的元素拷贝到以 result 为起始的位置上
/*****************************************************************************************/
template
OutputIter
copy_if(InputIter first, InputIter last, OutputIter result, UnaryPredicate unary_pred)
{
for (; first != last; ++first)
{
if (unary_pred(*first))
*result++ = *first;
}
return result;
}
/*****************************************************************************************/
// copy_n
// 把 [first, first + n)区间上的元素拷贝到 [result, result + n)上
// 返回一个 pair 分别指向拷贝结束的尾部
/*****************************************************************************************/
template
mystl::pair
unchecked_copy_n(InputIter first, Size n, OutputIter result, mystl::input_iterator_tag)
{
for (; n > 0; --n, ++first, ++result)
{
*result = *first;
}
return mystl::pair(first, result);
}
template
mystl::pair
unchecked_copy_n(RandomIter first, Size n, OutputIter result,
mystl::random_access_iterator_tag)
{
auto last = first + n;
return mystl::pair(last, mystl::copy(first, last, result));
}
template
mystl::pair
copy_n(InputIter first, Size n, OutputIter result)
{
return unchecked_copy_n(first, n, result, iterator_category(first));
}
/*****************************************************************************************/
// move
// 把 [first, last)区间内的元素移动到 [result, result + (last - first))内
/*****************************************************************************************/
// input_iterator_tag 版本
template
OutputIter
unchecked_move_cat(InputIter first, InputIter last, OutputIter result,
mystl::input_iterator_tag)
{
for (; first != last; ++first, ++result)
{
*result = mystl::move(*first);
}
return result;
}
// ramdom_access_iterator_tag 版本
template
OutputIter
unchecked_move_cat(RandomIter first, RandomIter last, OutputIter result,
mystl::random_access_iterator_tag)
{
for (auto n = last - first; n > 0; --n, ++first, ++result)
{
*result = mystl::move(*first);
}
return result;
}
template
OutputIter
unchecked_move(InputIter first, InputIter last, OutputIter result)
{
return unchecked_move_cat(first, last, result, iterator_category(first));
}
// 为 trivially_copy_assignable 类型提供特化版本
template
typename std::enable_if<
std::is_same::type, Up>::value &&
std::is_trivially_move_assignable::value,
Up*>::type
unchecked_move(Tp* first, Tp* last, Up* result)
{
const size_t n = static_cast(last - first);
if (n != 0)
std::memmove(result, first, n * sizeof(Up));
return result + n;
}
template
OutputIter move(InputIter first, InputIter last, OutputIter result)
{
return unchecked_move(first, last, result);
}
/*****************************************************************************************/
// move_backward
// 将 [first, last)区间内的元素移动到 [result - (last - first), result)内
/*****************************************************************************************/
// bidirectional_iterator_tag 版本
template
BidirectionalIter2
unchecked_move_backward_cat(BidirectionalIter1 first, BidirectionalIter1 last,
BidirectionalIter2 result, mystl::bidirectional_iterator_tag)
{
while (first != last)
*--result = mystl::move(*--last);
return result;
}
// random_access_iterator_tag 版本
template
RandomIter2
unchecked_move_backward_cat(RandomIter1 first, RandomIter1 last,
RandomIter2 result, mystl::random_access_iterator_tag)
{
for (auto n = last - first; n > 0; --n)
*--result = mystl::move(*--last);
return result;
}
template
BidirectionalIter2
unchecked_move_backward(BidirectionalIter1 first, BidirectionalIter1 last,
BidirectionalIter2 result)
{
return unchecked_move_backward_cat(first, last, result,
iterator_category(first));
}
// 为 trivially_copy_assignable 类型提供特化版本
template
typename std::enable_if<
std::is_same::type, Up>::value &&
std::is_trivially_move_assignable::value,
Up*>::type
unchecked_move_backward(Tp* first, Tp* last, Up* result)
{
const size_t n = static_cast(last - first);
if (n != 0)
{
result -= n;
std::memmove(result, first, n * sizeof(Up));
}
return result;
}
template
BidirectionalIter2
move_backward(BidirectionalIter1 first, BidirectionalIter1 last, BidirectionalIter2 result)
{
return unchecked_move_backward(first, last, result);
}
/*****************************************************************************************/
// equal
// 比较第一序列在 [first, last)区间上的元素值是否和第二序列相等
/*****************************************************************************************/
template
bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2)
{
for (; first1 != last1; ++first1, ++first2)
{
if (*first1 != *first2)
return false;
}
return true;
}
// 重载版本使用函数对象 comp 代替比较操作
template
bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, Compared comp)
{
for (; first1 != last1; ++first1, ++first2)
{
if (!comp(*first1, *first2))
return false;
}
return true;
}
/*****************************************************************************************/
// fill_n
// 从 first 位置开始填充 n 个值
/*****************************************************************************************/
template
OutputIter unchecked_fill_n(OutputIter first, Size n, const T& value)
{
for (; n > 0; --n, ++first)
{
*first = value;
}
return first;
}
// 为 one-byte 类型提供特化版本
template
typename std::enable_if<
std::is_integral::value && sizeof(Tp) == 1 &&
!std::is_same::value &&
std::is_integral::value && sizeof(Up) == 1,
Tp*>::type
unchecked_fill_n(Tp* first, Size n, Up value)
{
if (n > 0)
{
std::memset(first, (unsigned char)value, (size_t)(n));
}
return first + n;
}
template
OutputIter fill_n(OutputIter first, Size n, const T& value)
{
return unchecked_fill_n(first, n, value);
}
/*****************************************************************************************/
// fill
// 为 [first, last)区间内的所有元素填充新值
/*****************************************************************************************/
template
void fill_cat(ForwardIter first, ForwardIter last, const T& value,
mystl::forward_iterator_tag)
{
for (; first != last; ++first)
{
*first = value;
}
}
template
void fill_cat(RandomIter first, RandomIter last, const T& value,
mystl::random_access_iterator_tag)
{
fill_n(first, last - first, value);
}
template
void fill(ForwardIter first, ForwardIter last, const T& value)
{
fill_cat(first, last, value, iterator_category(first));
}
/*****************************************************************************************/
// lexicographical_compare
// 以字典序排列对两个序列进行比较,当在某个位置发现第一组不相等元素时,有下列几种情况:
// (1)如果第一序列的元素较小,返回 true ,否则返回 false
// (2)如果到达 last1 而尚未到达 last2 返回 true
// (3)如果到达 last2 而尚未到达 last1 返回 false
// (4)如果同时到达 last1 和 last2 返回 false
/*****************************************************************************************/
template
bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
{
if (*first1 < *first2)
return true;
if (*first2 < *first1)
return false;
}
return first1 == last1 && first2 != last2;
}
// 重载版本使用函数对象 comp 代替比较操作
template
bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2, Compred comp)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
{
if (comp(*first1, *first2))
return true;
if (comp(*first2, *first1))
return false;
}
return first1 == last1 && first2 != last2;
}
// 针对 const unsigned char* 的特化版本
bool lexicographical_compare(const unsigned char* first1,
const unsigned char* last1,
const unsigned char* first2,
const unsigned char* last2)
{
const auto len1 = last1 - first1;
const auto len2 = last2 - first2;
// 先比较相同长度的部分
const auto result = std::memcmp(first1, first2, mystl::min(len1, len2));
// 若相等,长度较长的比较大
return result != 0 ? result < 0 : len1 < len2;
}
/*****************************************************************************************/
// mismatch
// 平行比较两个序列,找到第一处失配的元素,返回一对迭代器,分别指向两个序列中失配的元素
/*****************************************************************************************/
template
mystl::pair
mismatch(InputIter1 first1, InputIter1 last1, InputIter2 first2)
{
while (first1 != last1 && *first1 == *first2)
{
++first1;
++first2;
}
return mystl::pair(first1, first2);
}
// 重载版本使用函数对象 comp 代替比较操作
template
mystl::pair
mismatch(InputIter1 first1, InputIter1 last1, InputIter2 first2, Compred comp)
{
while (first1 != last1 && comp(*first1, *first2))
{
++first1;
++first2;
}
return mystl::pair(first1, first2);
}
} // namespace mystl
#endif // !MYTINYSTL_ALGOBASE_H_
================================================
FILE: MyTinySTL/algorithm.h
================================================
#ifndef MYTINYSTL_ALGORITHM_H_
#define MYTINYSTL_ALGORITHM_H_
// 这个头文件包含了 mystl 的所有算法,包括基本算法,数值算法,heap 算法,set 算法和其他算法
#include "algobase.h"
#include "algo.h"
#include "set_algo.h"
#include "heap_algo.h"
#include "numeric.h"
namespace mystl
{
} // namespace mystl
#endif // !MYTINYSTL_ALGORITHM_H_
================================================
FILE: MyTinySTL/alloc.h
================================================
#ifndef MYTINYSTL_ALLOC_H_
#define MYTINYSTL_ALLOC_H_
// 这个头文件包含一个类 alloc,用于分配和回收内存,以内存池的方式实现
//
// 从 v2.0.0 版本开始,将不再使用内存池,这个文件将被弃用,但暂时保留
//
// 注意!!!
// 我知道这个文件里很多实现是错的,这是很久很久前写的了,后面已经不用这个东西了,
// 所以我也没再维护,有诸多问题,已经有人在issue中都提了,free_list的修改,
// 指针作为参数时没实际修改到原指针,等等。相信会看这么仔细的,大部分都是
// 初学C++的朋友,大佬都不会看这些玩具了,所以其中的错误,就留给对内存池实现
// 感兴趣的朋友去修改啦!
#include
#include
#include
namespace mystl
{
// 共用体: FreeList
// 采用链表的方式管理内存碎片,分配与回收小内存(<=4K)区块
union FreeList
{
union FreeList* next; // 指向下一个区块
char data[1]; // 储存本块内存的首地址
};
// 不同内存范围的上调大小
enum
{
EAlign128 = 8,
EAlign256 = 16,
EAlign512 = 32,
EAlign1024 = 64,
EAlign2048 = 128,
EAlign4096 = 256
};
// 小对象的内存大小
enum { ESmallObjectBytes = 4096 };
// free lists 个数
enum { EFreeListsNumber = 56 };
// 空间配置类 alloc
// 如果内存较大,超过 4096 bytes,直接调用 std::malloc, std::free
// 当内存较小时,以内存池管理,每次配置一大块内存,并维护对应的自由链表
class alloc
{
private:
static char* start_free; // 内存池起始位置
static char* end_free; // 内存池结束位置
static size_t heap_size; // 申请 heap 空间附加值大小
static FreeList* free_list[EFreeListsNumber]; // 自由链表
public:
static void* allocate(size_t n);
static void deallocate(void* p, size_t n);
static void* reallocate(void* p, size_t old_size, size_t new_size);
private:
static size_t M_align(size_t bytes);
static size_t M_round_up(size_t bytes);
static size_t M_freelist_index(size_t bytes);
static void* M_refill(size_t n);
static char* M_chunk_alloc(size_t size, size_t &nobj);
};
// 静态成员变量初始化
char* alloc::start_free = nullptr;
char* alloc::end_free = nullptr;
size_t alloc::heap_size = 0;
FreeList* alloc::free_list[EFreeListsNumber] = {
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr
};
// 分配大小为 n 的空间, n > 0
inline void* alloc::allocate(size_t n)
{
FreeList* my_free_list;
FreeList* result;
if (n > static_cast(ESmallObjectBytes))
return std::malloc(n);
my_free_list = free_list[M_freelist_index(n)];
result = my_free_list;
if (result == nullptr)
{
void* r = M_refill(M_round_up(n));
return r;
}
my_free_list = result->next;
return result;
}
// 释放 p 指向的大小为 n 的空间, p 不能为 0
inline void alloc::deallocate(void* p, size_t n)
{
if (n > static_cast(ESmallObjectBytes))
{
std::free(p);
return;
}
FreeList* q = reinterpret_cast(p);
FreeList* my_free_list;
my_free_list = free_list[M_freelist_index(n)];
q->next = my_free_list;
my_free_list = q;
}
// 重新分配空间,接受三个参数,参数一为指向新空间的指针,参数二为原来空间的大小,参数三为申请空间的大小
inline void* alloc::reallocate(void* p, size_t old_size, size_t new_size)
{
deallocate(p, old_size);
p = allocate(new_size);
return p;
}
// bytes 对应上调大小
inline size_t alloc::M_align(size_t bytes)
{
if (bytes <= 512)
{
return bytes <= 256
? bytes <= 128 ? EAlign128 : EAlign256
: EAlign512;
}
return bytes <= 2048
? bytes <= 1024 ? EAlign1024 : EAlign2048
: EAlign4096;
}
// 将 bytes 上调至对应区间大小
inline size_t alloc::M_round_up(size_t bytes)
{
return ((bytes + M_align(bytes) - 1) & ~(M_align(bytes) - 1));
}
// 根据区块大小,选择第 n 个 free lists
inline size_t alloc::M_freelist_index(size_t bytes)
{
if (bytes <= 512)
{
return bytes <= 256
? bytes <= 128
? ((bytes + EAlign128 - 1) / EAlign128 - 1)
: (15 + (bytes + EAlign256 - 129) / EAlign256)
: (23 + (bytes + EAlign512 - 257) / EAlign512);
}
return bytes <= 2048
? bytes <= 1024
? (31 + (bytes + EAlign1024 - 513) / EAlign1024)
: (39 + (bytes + EAlign2048 - 1025) / EAlign2048)
: (47 + (bytes + EAlign4096 - 2049) / EAlign4096);
}
// 重新填充 free list
void* alloc::M_refill(size_t n)
{
size_t nblock = 10;
char* c = M_chunk_alloc(n, nblock);
FreeList* my_free_list;
FreeList* result, *cur, *next;
// 如果只有一个区块,就把这个区块返回给调用者,free list 没有增加新节点
if (nblock == 1)
return c;
// 否则把一个区块给调用者,剩下的纳入 free list 作为新节点
my_free_list = free_list[M_freelist_index(n)];
result = (FreeList*)c;
my_free_list = next = (FreeList*)(c + n);
for (size_t i = 1; ; ++i)
{
cur = next;
next = (FreeList*)((char*)next + n);
if (nblock - 1 == i)
{
cur->next = nullptr;
break;
}
else
{
cur->next = next;
}
}
return result;
}
// 从内存池中取空间给 free list 使用,条件不允许时,会调整 nblock
char* alloc::M_chunk_alloc(size_t size, size_t& nblock)
{
char* result;
size_t need_bytes = size * nblock;
size_t pool_bytes = end_free - start_free;
// 如果内存池剩余大小完全满足需求量,返回它
if (pool_bytes >= need_bytes)
{
result = start_free;
start_free += need_bytes;
return result;
}
// 如果内存池剩余大小不能完全满足需求量,但至少可以分配一个或一个以上的区块,就返回它
else if (pool_bytes >= size)
{
nblock = pool_bytes / size;
need_bytes = size * nblock;
result = start_free;
start_free += need_bytes;
return result;
}
// 如果内存池剩余大小连一个区块都无法满足
else
{
if (pool_bytes > 0)
{ // 如果内存池还有剩余,把剩余的空间加入到 free list 中
FreeList* my_free_list = free_list[M_freelist_index(pool_bytes)];
((FreeList*)start_free)->next = my_free_list;
my_free_list = (FreeList*)start_free;
}
// 申请 heap 空间
size_t bytes_to_get = (need_bytes << 1) + M_round_up(heap_size >> 4);
start_free = (char*)std::malloc(bytes_to_get);
if (!start_free)
{ // heap 空间也不够
FreeList* my_free_list, *p;
// 试着查找有无未用区块,且区块足够大的 free list
for (size_t i = size; i <= ESmallObjectBytes; i += M_align(i))
{
my_free_list = free_list[M_freelist_index(i)];
p = my_free_list;
if (p)
{
my_free_list = p->next;
start_free = (char*)p;
end_free = start_free + i;
return M_chunk_alloc(size, nblock);
}
}
std::printf("out of memory");
end_free = nullptr;
throw std::bad_alloc();
}
end_free = start_free + bytes_to_get;
heap_size += bytes_to_get;
return M_chunk_alloc(size, nblock);
}
}
} // namespace mystl
#endif // !MYTINYSTL_ALLOC_H_
================================================
FILE: MyTinySTL/allocator.h
================================================
#ifndef MYTINYSTL_ALLOCATOR_H_
#define MYTINYSTL_ALLOCATOR_H_
// 这个头文件包含一个模板类 allocator,用于管理内存的分配、释放,对象的构造、析构
#include "construct.h"
#include "util.h"
namespace mystl
{
// 模板类:allocator
// 模板函数代表数据类型
template
class allocator
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
public:
static T* allocate();
static T* allocate(size_type n);
static void deallocate(T* ptr);
static void deallocate(T* ptr, size_type n);
static void construct(T* ptr);
static void construct(T* ptr, const T& value);
static void construct(T* ptr, T&& value);
template
static void construct(T* ptr, Args&& ...args);
static void destroy(T* ptr);
static void destroy(T* first, T* last);
};
template
T* allocator::allocate()
{
return static_cast(::operator new(sizeof(T)));
}
template
T* allocator::allocate(size_type n)
{
if (n == 0)
return nullptr;
return static_cast(::operator new(n * sizeof(T)));
}
template
void allocator