MFC - 链接列表


链表是一种线性数据结构,其中每个元素都是一个单独的对象列表的每个元素(我们将其称为节点)包含两项——数据和对下一个节点的引用。最后一个节点有一个对 null 的引用。

链表是一种由一组节点组成的数据结构,这些节点一起代表一个序列。它是一种用结构来存储数据的方法,以便程序员可以在需要时自动创建一个新的位置来存储数据。它的一些显着特征是 -

  • 链接列表是包含项目的链接序列。

  • 每个链接都包含到另一个链接的连接。

  • 列表中的每个项目称为一个节点。

  • 如果列表至少包含一个节点,则新节点将定位为列表中的最后一个元素。

  • 如果列表只有一个节点,则该节点代表第一项和最后一项。

有两种类型的链接列表 -

单链表

单链表是一种数据结构。在单链表中,列表中的每个节点都存储该节点的内容以及指向列表中下一个节点的指针或引用。

单链表

双向链表

双向链表是一种链接数据结构,由一组称为节点的顺序链接记录组成。每个节点包含两个字段,它们是节点序列中前一个节点和下一个节点的引用。

双链表

CList类

MFC提供了一个类CList,它是一个模板链表实现,并且工作得很好。CList 列表的Behave类似于双向链接列表。POSITION 类型的变量是列表的键。您可以使用 POSITION 变量作为迭代器来顺序遍历列表,并作为书签来保存位置。

以下是 CList 对象上的不同操作 -

创建CList对象

要创建 CList 值或对象的集合,必须首先确定集合值的类型。您可以使用现有的基本数据类型之一,例如 int、CString、double 等,如下面的代码所示。

CList<double, double>m_list;

添加项目

要添加项目,可以使用 CList::AddTail() 函数。它在列表末尾添加一个项目。要在列表的开头添加元素,可以使用 CList::AddHead() 函数。在 OnInitDialog() CList 中,创建对象并添加四个值,如以下代码所示。

CList<double, double>m_list;

//Add items to the list
m_list.AddTail(100.75);
m_list.AddTail(85.26);
m_list.AddTail(95.78);
m_list.AddTail(90.1);

检索物品

POSITION 类型的变量是列表的键。您可以使用 POSITION 变量作为迭代器来顺序遍历列表。

步骤 1 - 要从列表中检索元素,我们可以使用以下代码来检索所有值。

//iterate the list
POSITION pos = m_list.GetHeadPosition();
while (pos) { 
   double nData = m_list.GetNext(pos);
   CString strVal;
   strVal.Format(L"%.2f\n", nData);
   m_strText.Append(strVal);
}

步骤 2 - 这是完整的 CMFCCListDemoDlg::OnInitDialog() 函数。

BOOL CMFCCListDemoDlg::OnInitDialog() {
   CDialogEx::OnInitDialog();

   // Set the icon for this dialog. The framework does this automatically
   // when the application's main window is not a dialog
   SetIcon(m_hIcon, TRUE);             // Set big icon
   SetIcon(m_hIcon, FALSE);             // Set small icon

   // TODO: Add extra initialization here
   CList<double, double>m_list;

   //Add items to the list
   m_list.AddTail(100.75);
   m_list.AddTail(85.26);
   m_list.AddTail(95.78);
   m_list.AddTail(90.1);

   //iterate the list
   POSITION pos = m_list.GetHeadPosition();
   while (pos) {
      double nData = m_list.GetNext(pos);
      CString strVal;
      strVal.Format(L"%.f\n", nData);
      m_strText.Append(strVal);
   }

   UpdateData(FALSE);
 
   return TRUE; // return TRUE unless you set the focus to a control
}

步骤 3 - 编译并执行上述代码后,您将看到以下输出。

取回

在中间添加项目

要在列表中间添加项目,可以使用 CList::.InsertAfter() 和 CList::.InsertBefore() 函数。它需要两个参数 - 首先是位置(可以添加的位置),其次是值。

步骤 1 - 让我们插入一个新项目,如以下代码所示。

BOOL CMFCCListDemoDlg::OnInitDialog() {
   CDialogEx::OnInitDialog();
   
   // Set the icon for this dialog. The framework does this automatically
   // when the application's main window is not a dialog
   SetIcon(m_hIcon, TRUE);             // Set big icon
   SetIcon(m_hIcon, FALSE);          // Set small icon

   // TODO: Add extra initialization here
   CList<double, double>m_list;

   //Add items to the list
   m_list.AddTail(100.75);
   m_list.AddTail(85.26);
   m_list.AddTail(95.78);
   m_list.AddTail(90.1);

   POSITION position = m_list.Find(85.26);
   m_list.InsertBefore(position, 200.0);
   m_list.InsertAfter(position, 300.0);

   //iterate the list
   POSITION pos = m_list.GetHeadPosition();
   while (pos) {
      double nData = m_list.GetNext(pos);
      CString strVal;
      strVal.Format(L"%.2f\n", nData);
      m_strText.Append(strVal);
   }

   UpdateData(FALSE);

   return TRUE; // return TRUE unless you set the focus to a control
}

步骤 2 - 您现在可以看到,我们首先检索了值 85.26 的位置,然后在该值之前插入一个元素,在该值之后插入一个元素。

步骤 3 - 编译并执行上述代码后,您将看到以下输出。

添加项目

更新项目值

要更新数组中间的项目,可以使用 CArray::.SetAt() 函数。它需要两个参数——第一是位置,第二是值。

让我们将列表中的 300.00 更新为 400,如以下代码所示。

BOOL CMFCCListDemoDlg::OnInitDialog() {
   CDialogEx::OnInitDialog();

   // Set the icon for this dialog. The framework does this automatically
   // when the application's main window is not a dialog
   SetIcon(m_hIcon, TRUE);              // Set big icon
   SetIcon(m_hIcon, FALSE);            // Set small icon

   // TODO: Add extra initialization here
   CList<double, double>m_list;

   //Add items to the list
   m_list.AddTail(100.75);
   m_list.AddTail(85.26);
   m_list.AddTail(95.78);
   m_list.AddTail(90.1);

   POSITION position = m_list.Find(85.26);
   m_list.InsertBefore(position, 200.0);
   m_list.InsertAfter(position, 300.0);

   position = m_list.Find(300.00);
   m_list.SetAt(position, 400.00);

   //iterate the list
   POSITION pos = m_list.GetHeadPosition();
   while (pos) {
      double nData = m_list.GetNext(pos);
      CString strVal;
      strVal.Format(L"%.2f\n", nData);
      m_strText.Append(strVal);
   }

   UpdateData(FALSE);

   return TRUE; // return TRUE unless you set the focus to a control
}

当上面的代码被编译并执行时,您将看到以下输出。您现在可以看到值 300.00 已更新为 400.00。

更新项目

删除项目

要删除任何特定项目,您可以使用 CList::RemoveAt() 函数。要从列表中删除所有元素,可以使用 CList::RemoveAll() 函数。

让我们删除该元素,其值为 95.78。

BOOL CMFCCListDemoDlg::OnInitDialog() {
   CDialogEx::OnInitDialog();

   // Set the icon for this dialog. The framework does this automatically
   // when the application's main window is not a dialog
   SetIcon(m_hIcon, TRUE);              // Set big icon
   SetIcon(m_hIcon, FALSE);             // Set small icon

   // TODO: Add extra initialization here
   CList<double, double>m_list;

   //Add items to the list
   m_list.AddTail(100.75);
   m_list.AddTail(85.26);
   m_list.AddTail(95.78);
   m_list.AddTail(90.1);

   POSITION position = m_list.Find(85.26);
   m_list.InsertBefore(position, 200.0);
   m_list.InsertAfter(position, 300.0);
   
   position = m_list.Find(300.00);
   m_list.SetAt(position, 400.00);

   position = m_list.Find(95.78);
   m_list.RemoveAt(position);

   //iterate the list
   POSITION pos = m_list.GetHeadPosition();
   while (pos) {
      double nData = m_list.GetNext(pos);
      CString strVal;
      strVal.Format(L"%.2f\n", nData);
      m_strText.Append(strVal);
   }
   UpdateData(FALSE);
   
   return TRUE; // return TRUE unless you set the focus to a control
}

当上面的代码被编译并执行时,您将看到以下输出。您现在可以看到值 95.78 不再是列表的一部分。

移除物品