Featured image of post STL基础用法

STL基础用法


vector

头文件:#include<iostream> #include<vector> using namespace std;

打印函数printVector()

1
2
3
4
5
6
void printVector(vector<int> &v) {
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}

对象创建

  • 默认构造函数
    vector<int> v;
  • 初始化列表
    vector<int> v={1,2,3,4,5};
    vector<int> v({1,2,3,4,5});
  • 迭代器
    vector<int> v(v1.begin(), v1.end());//左闭右开
  • 全0初始化
    vector<int> v(10);
  • vector<int>变量名(a,b)
    vector<int> v(10,0);
  • 拷贝构造函数
    vector<int> v(v1);

赋值操作

  • 等号赋值
    vector<int> v=v1;
  • assign(迭代器)
    vector<int> v;
    v.assign(v1.begin(), v1.end());
    v.assign({1,2,3,4,5});
    v.assign(10,0);//10个0

插入操作

  • push_back(元素)
    v.push_back(1);//在末尾插入1
  • insert(迭代器,元素)
    v.insert(v.begin(), 1);//在开头插入1

删除操作

  • pop_back()
    v.pop_back();//删除最后一个元素
  • erase(迭代器)
    vector<int>::iterator it = v.erase(v.begin());//删除第一个元素并返回删除元素的下一位迭代器
  • clear()
    v.clear();//清空元素

扩容

  • resize(大小)
    v.resize(10);//将v的大小变为10
  • resize(大小,元素)
    v.resize(10,0);//将v的大小变为10,并将新的元素初始化为0

访问操作

  • 下标访问
    v[0];//越界不会报错
  • at(下标)
    v.at(0);//越界会报错
  • front()
    v.front();//返回第一个元素
  • back()
    v.back();//返回最后一个元素

其他操作

  • empty()
    v.empty();//判断是否为空
  • size()
    v.size();//返回大小
  • capacity()
    v.capacity();//返回容量

内存交换

  • swap(容器)
    v.swap(v1);//交换两个容器的元素
  • 缩容
    v.resize(100);
    v.resize(10);
    vector<int>(v).swap(v);//将v的容量(capacity)变为10
  • 内存清理
    vector<int>({}).swap(v);//将v的容量(capacity)变为0

空间预留

  • reserve(大小)
    v.reserve(100);//将v的容量(capacity)变为100

高效删除

1
2
3
4
void remove(vector<int>& v,int index){
    v[index] = v.back();//将最后一个元素和要删除的元素交换
    v.pop_back();
}

排序

  • sort(迭代器,迭代器)
    sort(v.begin(), v.end());//默认升序
  • sort(迭代器,迭代器,比较函数)
    sort(v.begin(), v.end(), greater<int>());//降序
  • sort(迭代器,迭代器,函数对象)
1
2
3
bool compare(int a, int b) {
    return a > b;
}

sort(v.begin(), v.end(), compare);//降序


string

头文件:#include<iostream> #include<string> using namespace std;

对象创建

  • 无参构造
    string s;
  • 初始化列表
    string s({'h','e','l','l','o'});
  • 字符串初始化
    string s("hello");
  • 字符串前n个字符初始化
    string s("hello", 3);//hel
  • 拷贝构造
    string s(s1);
  • a个字符b初始化
    string s(10, 'a');//aaaaaaaaaa

赋值操作

  • 字符串常量赋值
    s= "hello";
  • 字符串变量赋值
    s1= s;
  • 字符常量赋值
    string s
    s= 'a';
  • assign
    string s
    s.assign(s1.begin(), s1.end());
    s.assign("hello");
    s.assign("hello",3);//hel
    s.assign(10,'a');//aaaaaaaaaa
    s.assign(s1);

字符串拼接

  • 字符串常量拼接
    s= s + "hello";
  • 字符串变量拼接
    s= s + s1;
  • append
    s.append("hello");
    s.append("hello",3);//hel
    s.append(10,'a');//aaaaaaaaaa
    s.append(s1);
    s.append("hello",3,2);//lo
  • push_back
    s.push_back('a');//a

字符串比较

  • 字符串变量比较
    string s1="hello";
    string s2="hello";
    s1.compare(s2); 相等返回0,前大后小返回1,前小后大返回-1
  • 字符串常量比较
    s==s1相等返回1,不相等返回0

随机访问

  • 下标访问
    s[0];//越界不会报错
  • at访问
    s.at(0);//越界会报错
  • 修改
    s[0]= 'a';
    s.at(0)= 'a';

插入

  • insert(位置,字符串)
    s.insert(0, "hello");//在开头插入hello
  • insert(位置,常量,字符串)
    s.insert(0, 10, 'a');//在开头插入aaaaaaaaaa
  • insert(迭代器,字符)
    s.insert(s.begin(), 'a');//在开头插入a

删除

  • erase(位置,长度)
    s.erase(1, 5);//删除第1位的后面5位元素
  • erase(迭代器)
    s.erase(s.begin());//删除第一个元素
  • erase()
    s.erase();//清空元素
  • erase(长度)
    s.erase(10);//删除第10位后面的所有元素
  • erase(迭代器,迭代器)
    s.erase(s.begin(), s.end());//删除所有元素

查找

  • find(字符串)
    (int)s.find("hello");//返回hello的位置,没有找到返回-1
  • find(字符串,位置)
    s.find("hello", 1);//从第1位开始查找hello
  • find(字符)
    s.find('a');//返回a的位置
  • find(字符,位置)
    s.find('a', 1);//从第1位开始查找a -rfind(字符串)
    s.rfind("hello");//从右边开始找,返回hello的位置

数据替换

  • replace(位置,长度,字符串)
    s.replace(0, 5, "hello");//将第0位的后面5位替换为hello
  • replace(位置,长度,常量,字符串)
    s.replace(0, 5, 10, 'a');//将第0位的后面5位替换为aaaaaaaaaa
  • replace(迭代器,迭代器,字符串)
    s.replace(s.begin(), s.end(), "hello");//将所有元素替换为hello
  • replace(迭代器,迭代器,字符串,常量)
    s.replace(s.begin(), s.end(), "hello", 10);//将所有元素替换为hello的前10位

字符串截取

  • substr(位置,长度)
    s.substr(0, 5);//返回第0位的后面5位
  • substr(位置)
    s.substr(1);//返回第1位后面的所有元素

deque

头文件:#include<iostream> #include<deque> using namespace std;

打印函数printDeque()

1
2
3
4
5
void printDeque(deque<int>& d){
    for(deque<int>::iterator it=d.begin();it!=d.end();it++){
        cout<<*it<<" ";
    }
}

对象创建

  • 默认构造
    deque<int> d;
  • 初始化列表
    deque<int> d={1,2,3,4,5};
    deque<int> d({1,2,3,4,5});
  • 迭代器
    deque<int> d(d1.begin(), d1.end());//左闭右开
  • 全0初始化
    deque<int> d(10);
  • deque<int>变量名(a,b)
    deque<int> d(10,0);//10个0
  • 拷贝构造函数
    deque<int> d(d1);

赋值操作

  • 等号赋值
    deque<int> d; d=d1;
  • assign(迭代器)
    deque<int> d;
    d.assign(d1.begin(), d1.end());
  • 初始化列表
    d.assign({1,2,3,4,5});
  • 全0初始化
    d.assign(10,0);//10个0

大小操作

  • size()
    d.size();//返回大小
  • empty()
    d.empty();//判断是否为空
  • resize()
    d.resize(10);//将大小变为10,新的元素为0
    d.resize(10,2);//将大小变为10,新的元素为2

数据插入

  • push_back()
    d.push_back(1);//在末尾插入1
  • push_front()
    d.push_front(1);//在开头插入1
  • insert()
    d.insert(d.begin(), 1);//在开头插入1
    d.insert(d.begin(), 1);//在开头插入1
    d.insert(d.begin(), 1, 2);//在开头插入1个2
    d.insert(d.begin(), d1.begin(), d1.end());//在开头插入d1

数据删除

  • pop_back()
    d.pop_back();//删除最后一个元素
  • pop_front()
    d.pop_front();//删除第一个元素
  • erase()
    d.erase(d.begin());//删除第一个元素
    d.erase(d.begin(), d.end());//删除所有元素
  • clear()
    d.clear();//清空元素

随机访问

  • at()
    d.at(0);//越界会报错
  • []
    d[0];//越界不会报错
  • front()
    d.front();//返回第一个元素
  • back()
    d.back();//返回最后一个元素

stack

头文件:#include<iostream> #include<stack> using namespace std;

打印函数printStack(stack<int>&s)

1
2
3
4
5
6
7
void printStack(stack<int>&s){
    while(!s.empty()){
        cout<<s.top()<<" ";
        s.pop();
    }
    cout<<endl;
}

对象创建

  • 默认构造函数
    stack<int> s;
  • 拷贝构造函数
    stack<int> s(s1);

赋值操作

  • 等号赋值
    stack<int> s; s=s1;

入栈操作

  • push()
    s.push(1);//在栈顶插入1

出栈操作

  • pop()
    s.pop();//删除栈顶元素

获取栈顶元素

  • top()
    s.top();//返回栈顶元素

判空

  • empty()
    s.empty();//判断是否为空

大小操作

  • size()
    s.size();//返回大小

容器替换

  • 类型替换
    stack<int,vector<int>> s;//将stack的容器类型替换为vector

queue

头文件:#include<iostream> #include<queue> using namespace std;

打印函数printQueue(queue<int>&q)

1
2
3
4
5
6
7
void printQueue(queue<int>&q){
    while(!q.empty()){
        cout<<q.front()<<" ";
        q.pop();
    }
    cout<<endl;
}

对象创建

  • 默认构造函数
    queue<int> q;
  • 拷贝构造函数
    queue<int> q(q1);

赋值操作

  • 等号赋值
    queue<int> q; q=q1;

入队操作

  • push()
    q.push(1);//在队尾插入1

出队操作

  • pop()
    q.pop();//删除队首元素

获取队首元素

  • front()
    q.front();//返回队首元素

获取队尾元素

  • back()
    q.back();//返回队尾元素

大小操作

  • empty()
    q.empty();//判断是否为空
  • size()
    q.size();//返回大小

list

头文件:#include<iostream> #include<list> using namespace std;

打印函数printList(list<int>&l)

1
2
3
4
5
6
void printList(const list<int>&l){
    for(list<int>::const_iterator it=l.begin();it!=l.end();it++){
        cout<<*it<<" ";
    }
    cout<<endl;
}

对象创建

  • 默认构造函数
    list<int> l;
  • 初始化列表
    list<int> l={1,2,3,4,5};
    list<int> l({1,2,3,4,5});
  • 迭代器
    list<int> l(l1.begin(), l1.end());//左闭右开
  • 全0初始化
    list<int> l(10);
  • list<int>变量名(a,b)
    list<int> l(10,1);//10个1
  • 拷贝构造函数
    list<int> l(l1);

赋值操作

  • 等号赋值
    list<int> l; l=l1;
  • assign(迭代器)
    l.assign(l1.begin(), l1.end());
  • 初始化列表
    l.assign({1,2,3,4,5});
  • 全0初始化
    l.assign(10,0);//10个0

大小操作

  • size()
    l.size();//返回大小
  • empty()
    l.empty();//判断是否为空
  • resize()
    l.resize(10);//将大小变为10,新的元素为0
    l.resize(10,2);//将大小变为10,新的元素为2

数据插入

  • push_back()
    l.push_back(1);//在末尾插入1
  • push_front()
    l.push_front(1);//在开头插入1
  • insert()
    l.insert(l.begin(), 1);//在开头插入1
    l.insert(l.begin(), 2, 1);//在开头插入2个1
    l.insert(l.begin(), l1.begin(), l1.end());//在开头插入l1

数据删除

  • pop_back()
    l.pop_back();//删除最后一个元素
  • pop_front()
    l.pop_front();//删除第一个元素
  • erase()
    l.erase(l.begin());//删除第一个元素
    l.erase(l.begin(), l.end());//删除所有元素
  • clear()
    l.clear();//清空元素

随机访问

  • list不能随机访问
1
2
3
4
5
6
7
8
int getListItemByIndex(list<int> &l, int index){
    list<int>::iterator it = l.begin();
    while(index){
        it++;
        index--;
    }
    return *it;
}
  • front()
    l.front();//返回第一个元素
  • back()
    l.back();//返回最后一个元素

反转

  • reverse()
    l.reverse();//反转

排序

  • sort()
    l.sort();//默认升序
  • sort(函数对象)
    l.sort(compare);//降序
1
2
3
bool compare(int a, int b) {
    return a > b;
}

set

头文件:#include<iostream> #include<set> using namespace std;

打印函数printSet(set<int>&s)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void printSet(const set<int>&s){
    for(set<int>::const_iterator it=s.begin();it!=s.end();it++){
        cout<<*it<<" ";
    }
    cout<<endl;
}
void printMultiset(const multiset<int>&s){
    for(multiset<int>::const_iterator it=s.begin();it!=s.end();it++){
        cout<<*it<<" "; 
    }
    cout<<endl;
}

概念

  • set 有序集合
    • 容器内元素不重复
    • 每插入一个元素,容器中的元素会进行有序排列
  • multiset 有序集合
    • 容器内元素支持重复
    • 每插入一个元素,容器中的元素会进行有序排列

对象创建

  • 默认构造函数
    set<int> s;
  • 初始化列表
    set<int> s={1,2,3,4,5};
    set<int> s({1,2,3,4,5});
  • 迭代器
    set<int> s(s1.begin(), s1.end());//左闭右开
  • 拷贝构造函数
    set<int> s(s1);

赋值操作

  • 等号赋值
    set<int> s; s=s1;
  • 初始化列表
    s={1,2,3,4,5};

大小操作

  • size()
    s.size();//返回大小
  • empty()
    s.empty();//判断是否为空

插入操作

  • insert()
    s.insert(1);//插入1
  • insert(迭代器)
    vector<int> v={1,2,3,4,5}; s.insert(v.begin(),v.end());

数据查找

  • find()
    s.find(1);//返回1的位置的迭代器,没有找到返回s.end()

删除操作

  • erase()
    s.erase(1);//删除1
  • erase(迭代器)
    s.erase(s.find(1));//删除1
  • erase(迭代器,迭代器)
    s.erase(s.find(1),s.find(5));//删除1到5,左闭右开

数据统计

  • count()
    set<int> s={1,2,3,4,5}; s.count(1);//返回1的个数
    multiset<int> s={1,2,3,4,5,1,2,3,4,5}; s.count(1);//返回1的个数//2

排序规则

  • set 排序规则
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class CGaGa{
public:
    CGaGa(){
        _name="";
        _priority=-1;
    }
    CGaGa(string name,int pri):_name(name),_priority(pri){}

    bool operator<(const CGaGa&other)const{
        return _priority<other._priority;
    }

    void print()const{
        cout<<_name<<":"<<_priority<<endl; 
    }
private:
    string _name;
    int _priority;
};
int main(){
    set<CGaGa> s;
    s.insert(CGaGa("a",1));
    s.insert(CGaGa("b",2));
    s.insert(CGaGa("c",3));
    for(set<CGaGa>::iterator it=s.begin();it!=s.end();it++){
        it->print();//(*it).print()
    }
    return 0;
}

map

头文件:#include<iostream> #include<map> using namespace std;

打印函数printMap(map<int,int>&m)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void printMap(const map<int,int>&m){
    for(map<int,int>::const_iterator it=m.begin();it!=m.end();it++){
        cout<<it->first<<" "<<it->second<<endl;
    }
    cout<<endl;
}
void printMultimap(const multimap<int,int>&m){
    for(multimap<int,int>::const_iterator it=m.begin();it!=m.end();it++){
        cout<<it->first<<" "<<it->second<<endl;
    } 
    cout<<endl;
}

概念

  • pair<key,value>
    pair<int,int> p; p.first=1;p.second=2;
    pair<int,int> p(1,2);
    pair<int,int> p=make_pair(1,2);
  • map 映射
    • 容器内元素不重复
    • 每插入一个元素,容器中的元素会根据key进行有序排列
    • 每一个元素都是一个pair
  • multimap 映射
    • 容器内元素支持重复
    • 每插入一个元素,容器中的元素会根据key进行有序排列
    • 每一个元素都是一个pair

对象创建

  • 默认构造函数
    map<int,int> m;
  • 初始化列表
    map<int,int> m={{1,1},{2,2},{3,3}};
    map<int,int> m={ pair<int,int>(1,1), pair<int,int>(2,2), pair<int,int>(3,3) };
    map<int,int> m({ pair<int,int>(1,1), pair<int,int>(2,2), pair<int,int>(3,3) });
  • 迭代器
    map<int,int> m(m1.begin(), m1.end());//左闭右开
  • 拷贝构造函数
    map<int,int> m(m1);

赋值操作

  • 等号赋值
    map<int,int> m; m=m1;
  • 初始化列表
    map<int,int> m; m={{1,1},{2,2}};

大小操作

  • size()
    m.size();//返回大小
  • empty()
    m.empty();//判断是否为空

插入操作

  • insert()
    m.insert(pair<int,int>(1,1));
    m.insert(make_pair(2,2));
    m.insert(map<int,int>::value_type(3,3));
    m[4]=5//插入{4,5},如果已经存在则修改

数据查找

  • find()
    m.find(1);//返回key=1的位置的迭代器,没有找到返回m.end()

删除操作

  • erase()
    m.erase(1);//删除key=1的元素
  • erase(迭代器)
    m.erase(m.begin());//删除开始的元素
    m.erase(m.find(1));//删除key=1的元素
  • erase(迭代器,迭代器)
    m.erase(m.begin(),m.end());//删除所有元素
  • clear()
    m.clear();//清空元素

数据修改

  • []
    m[1]=2;//修改key=1的value为2
    m[1]++;//修改key=1的value加一
    m[2]-=3;//修改key=1的value减三

数据统计

  • count()
    map<int,int> m={ pair<int,int>(1,1), pair<int,int>(2,2), pair<int,int>(3,3) } m.count(1);//返回key=1的个数//1
    multimap<int,int> m={ pair<int,int>(1,1), pair<int,int>(2,2), pair<int,int>(3,3), pair<int,int>(1,1) }
    m.count(1);//返回key=1的个数//2

priority_queue

头文件:#include<iostream> #include<queue> using namespace std;

对象创建

  • 默认构造函数
    priority_queue<int> pq;//最大优先队列//大顶堆
    priority_queue<int,vector<int>,greater<int>> pq;//最小优先队列//小顶堆

入队操作

  • push()
    pq.push(1);//入队

获取队首元素

  • top()
    pq.top();//返回队首元素

出队操作

  • pop()
    pq.pop();//出队

大小操作

  • empty()
    pq.empty();//判断是否为空

自定义结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<queue>
using namespace std;
struct type{
    int key;
    int value;
    type(){key=0;value=0;}
    type(int k,int v):key(k),value(v){}
    bool operator<(const type&t)const{//<大顶堆,>小顶堆
        return value<t.value;
    }
};
int main(){
    priority_queue<type> pq;
    //priority_queue<type,vector<type>,less<type>> pq;
    pq.push(type(1,1));
    pq.push(type(2,2));
    pq.push(type(3,3));
    while(!pq.empty()){
        cout<<pq.top().key<<" "<<pq.top().value<<endl;
        pq.pop();
    }
}

unordered_set

头文件:#include<iostream> #include<unordered_set> using namespace std;

打印函数printUnorderedSet(unordered_set<int>&s)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void printUnorderedSet(const unordered_set<int>&s){
    for(unordered_set<int>::const_iterator it=s.begin();it!=s.end();it++){
        cout<<*it<<" "; 
    } 
    cout<<endl;
}
void printUnorderedMultiset(const unordered_multiset<int>&s){
    for(unordered_multiset<int>::const_iterator it=s.begin();it!=s.end();it++){
        cout<<*it<<" ";
    } 
    cout<<endl;
}

概念

  • unordered_set
    • 无序集合
    • 容器内元素不重复
  • unordered_multiset
    • 无序集合
    • 容器内元素支持重复

对象创建

  • 默认构造函数
    unordered_set<int> s;
  • 初始化列表
    unordered_set<int> s={1,2,3,4,5};
    unordered_set<int> s({1,2,3,4,5});
  • 迭代器
    unordered_set<int> s(s1.begin(), s1.end());//左闭右开
  • 拷贝构造函数
    unordered_set<int> s(s1);

赋值操作

  • 等号赋值
    unordered_set<int> s; s=s1;
  • 初始化列表
    unordered_set<int> s s={1,2,3,4,5};

大小操作

  • size()
    s.size();//返回大小
  • empty()
    s.empty();//判断是否为空

插入操作

  • insert()
    s.insert(1);//插入1
  • insert(迭代器)
    vector<int> v={1,2,3,4,5}; s.insert(v.begin(),v.end());

数据查找

  • find()
    s.find(1);//返回1的位置的迭代器,没有找到返回s.end()

删除操作

  • erase()
    s.erase(1);//删除1
  • erase(迭代器)
    s.erase(s.find(1));//删除1
  • clear()
    s.erase();//删除所有元素

数据统计

  • count()
    unordered_set<int> s={1,2,3,4,5}; s.count(1);//返回1的个数
    unordered_multiset<int> s={1,2,3,4,5,1,2,3,4,5}; s.count(1);//返回1的个数//2

unordered_map

头文件:#include<iostream> #include<unordered_map> using namespace std;

打印函数printUnorderedMap(unordered_map<int,int>&m)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void printUnorderedMap(const unordered_map<int,int>&m){
    for(unordered_map<int,int>::const_iterator it=m.begin();it!=m.end();it++){
        cout<<it->first<<" "<<it->second<<endl;
    }
    cout<<endl;
}
void printUnorderedMultimap(const unordered_multimap<int,int>&m){
    for(unordered_multimap<int,int>::const_iterator it=m.begin();it!=m.end();it++){
        cout<<it->first<<" "<<it->second<<endl;
    } 
    cout<<endl;
}

概念

  • unordered_map
    • 无序映射
    • 容器内元素不重复
    • 每一个元素都是一个pair
  • unordered_multimap
    • 无序映射
    • 容器内元素支持重复
    • 每一个元素都是一个pair

对象创建

  • 默认构造函数
    unordered_map<int,int> m;
  • 初始化列表
    unordered_map<int,int> m={{1,1},{2,2},{3,3}};
    unordered_map<int,int> m={ pair<int,int>(1,1), pair<int,int>(2,2), pair<int,int>(3,3) }
    unordered_map<int,int> m({1,1},{2,2},{3,3});
  • 迭代器
    unordered_map<int,int> m(m1.begin(), m1.end());//左闭右开
  • 拷贝构造函数
    unordered_map<int,int> m(m1);

赋值操作

  • 等号赋值
    unordered_map<int,int> m; m=m1;
  • 初始化列表
    unordered_map<int,int> m; m={{1,1},{2,2}};

大小操作

  • size()
    m.size();//返回大小
  • empty()
    m.empty();//判断是否为空

插入操作

  • insert()
    m.insert(pair<int,int>(1,1));
    m.insert(make_pair(2,2));
    m.insert(unordered_map<int,int>::value_type(3,3));
    m[4]=5//插入{4,5},如果已经存在则修改

数据查找

  • find()
    m.find(1);//返回key=1的位置的迭代器,没有找到返回m.end()

删除操作

  • erase()
    m.erase(1);//删除key=1的元素
  • erase(迭代器)
    m.erase(m.begin());//删除开始的元素
  • erase(迭代器,迭代器)
    m.erase(m.begin(),m.end());//删除所有元素
  • clear()
    m.clear();//清空元素

数据修改

  • []
    m[1]=2;//修改key=1的value为2
    m[1]++;//修改key=1的value加一
    m[2]-=3;//修改key=1的value减三

数据统计

  • count()
    unordered_map<int,int> m={ pair<int,int>(1,1), pair<int,int>(2,2), pair<int,int>(3,3) } m.count(1);//返回key=1的个数//1
    unordered_multimap<int,int> m={ pair<int,int>(1,1), pair<int,int>(1,2), pair<int,int>(3,3), } m.count(1);//返回key=1的个数//2

Think more and practice more!
微信:zxcyuijkl
使用 Hugo 构建
主题 StackJimmy 设计