C++ List详解

发布时间:2023-05-18

一、C List源码

C++标准库中的List是一个双向链表容器,它允许快速插入和删除元素,但随机访问元素的效率略低于vector。下面是List的基本定义:

#include <list>
using namespace std;
list<int> myList;

这里创建了一个名为myList的List对象,它存储的是整型类型。注意,一旦在程序中创建了List对象,我们就可以使用它的很多方法了。 由于List的实现是基于双向链表的,因此它的底层实现需要使用大量的指针。下面是标准C++库中List实现中的核心代码:

template <typename T>
struct _List_node
{
    _List_node* _Prev;
    _List_node* _Next;
    T _Value;
    _List_node(const T& _Val = T())
        : _Prev(nullptr), _Next(nullptr), _Value(_Val)
    {}
};
template <typename T>
class list
{
public:
    // ...
private:
    _List_node<T>* _Head;
    _List_node<T>* _Tail;
    size_t _Size;
}

二、C List用法

List的用法与vector和deque非常相似。我们可以使用push_front和push_back方法在List的头部和尾部插入元素,可以使用pop_front和pop_back方法删除元素。另外,我们可以使用迭代器来遍历List中存储的元素,或者使用size方法来获取List中元素的数量。 下面是一组List的基本用法示例:

// 创建一个List对象
list<int> myList;
// 在List尾部插入若干元素
for (int i = 0; i < 5; ++i)
    myList.push_back(i);
// 在List头部插入若干元素
for (int i = 0; i < 5; ++i)
    myList.push_front(i);
// 遍历List中的所有元素
for (auto iter = myList.begin(); iter != myList.end(); ++iter)
    cout << *iter << endl;
// 删除头部元素
myList.pop_front();
// 删除尾部元素
myList.pop_back();
// 获取List中元素的数量
cout << myList.size() << endl;

三、C List容器

List属于C++标准库的容器之一,容器是用于存储数据的数据结构。List是一个双向链表,与vector和deque相比,它具有插入和删除元素更快的优势,但随机访问元素的效率略低。

四、C语言 List

对于C语言开发人员,也可以使用List。List对应的头文件是<glib.h>,下面是一个简单的C语言List程序示例:

#include <stdio.h>
#include <glib.h>
int main()
{
    GList* list = NULL;
    for (int i = 0; i < 5; ++i)
        list = g_list_append(list, GINT_TO_POINTER(i));
    for (GList* iter = list; iter; iter = iter->next)
        printf("%d\n", GPOINTER_TO_INT(iter->data));
    return 0;
}

五、C List定义

在C++中,我们可以使用template<typename T> class list来定义一个List,其中T是指List存储的元素类型。我们可以根据需要在List中存储不同类型的元素,例如整型、字符型、字符串等。

六、查找List中最大值C语言

下面是一个在C语言中查找List中最大值的程序示例:

#include <stdio.h>
#include <limits.h>
#include <glib.h>
int main()
{
    GList* list = NULL;
    for (int i = 0; i < 5; ++i)
        list = g_list_append(list, GINT_TO_POINTER(i));
    int max = INT_MIN;
    for (GList* iter = list; iter; iter = iter->next)
    {
        int val = GPOINTER_TO_INT(iter->data);
        if (val > max)
            max = val;
    }
    printf("Max value: %d\n", max);
    return 0;
}

七、C List逆序

List的逆序操作可以使用std::reversestd::reverse_copy方法实现,下面是一个示例程序:

#include <iostream>
#include <algorithm>
#include <list>
using namespace std;
int main()
{
    list<int> myList;
    for (int i = 0; i < 5; ++i)
        myList.push_back(i);
    // 使用std::reverse逆序
    reverse(myList.begin(), myList.end());
    // 使用List自带的reverse方法逆序
    myList.reverse();
    // 输出逆序后的元素
    for (auto iter = myList.begin(); iter != myList.end(); ++iter)
        cout << *iter << " ";
    cout << endl;
    return 0;
}

八、CListCtrl设置选中行

MFC中的CListCtrl可以使用SetItemStateGetItemState分别设置和获取ListCtrl中单元格的状态,下面是一个示例程序:

BOOL CMyDlg::OnInitDialog()
{
    // 初始化ListCtrl
    m_listCtrl.InsertColumn(0, _T("Name"));
    m_listCtrl.InsertColumn(1, _T("Age"));
    // 添加若干项
    m_listCtrl.InsertItem(0, _T("Tom"));
    m_listCtrl.SetItemText(0, 1, _T("20"));
    m_listCtrl.InsertItem(1, _T("Jerry"));
    m_listCtrl.SetItemText(1, 1, _T("22"));
    // 设置第一项为选中状态
    m_listCtrl.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
    return TRUE;
}

九、C Listen

C++标准库中的List可以存储不同类型的元素,因此我们可以创建一个包含多种类型元素的List,例如整型、字符型、字符串等。下面是一个包含不同类型元素的List程序示例:

#include <iostream>
#include <list>
using namespace std;
int main()
{
    list<auto> myList;
    myList.push_back(1);
    myList.push_back(2.3);
    myList.push_back('a');
    myList.push_back("hello");
    // 输出List中所有元素
    for (auto iter = myList.begin(); iter != myList.end(); ++iter)
    {
        cout << *iter << " ";
    }
    cout << endl;
    return 0;
}

十、C ListBox拖拽选取

MFC中的CListBox可以使用LB_SETCURSELLB_SETSELLB_SELITEMRANGE等方法实现ListBox的拖拽选取功能,下面是一个示例程序:

BOOL CMyDlg::OnInitDialog()
{
    // 初始化ListBox
    m_listBox.AddString(_T("Item 1"));
    m_listBox.AddString(_T("Item 2"));
    m_listBox.AddString(_T("Item 3"));
    m_listBox.AddString(_T("Item 4"));
    m_listBox.AddString(_T("Item 5"));
    return TRUE;
}
void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
    // 鼠标左键按下
    m_bLButtonDown = true;
    m_ptLButtonDown = point;
}
void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
    // 鼠标移动
    if (m_bLButtonDown)
    {
        // 根据两点坐标计算出矩形区域
        CRect rect(m_ptLButtonDown, point);
        rect.NormalizeRect();
        // 选取矩形区域内所有的ListBox项
        int start = m_listBox.ItemFromPoint(rect.TopLeft());
        if (start == LB_ERR)
            start = 0;
        int end = m_listBox.ItemFromPoint(rect.BottomRight());
        if (end == LB_ERR)
            end = start;
        m_listBox.SelItemRange(true, start, end);
    }
}
void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
    // 鼠标左键弹起
    m_bLButtonDown = false;
    m_listBox.SetCurSel(0);
}