【C++養成計劃】數據結構——鏈表list(Day11)

寫在前面:大家好!我是【AI 菌】,一枚愛彈吉他的程序員。我熱愛AI、熱愛分享、熱愛開源! 這博客是我對學習的一點總結與思考。如果您也對 深度學習、機器視覺、算法、C++、Python 感興趣,可以關注我的動態,我們一起學習,一起進步~
我的博客地址爲:【AI 菌】的博客

前言:
這一次,我整理了C++中 list類整套用法,結合數據結構鏈表:面試官:線性表、順序表、鏈表的區別是什麼?的知識學起來會更好。

相關文章:【C++21天養成計劃】



1. List 類

list 是順序容器,它允許在序列中任意位置進行常量時間的插入和擦除操作,並在兩個方向上進行迭代。

list 容器是雙向鏈表;雙向鏈表可以將它們所包含的每個元素存儲在不同的、不相關的存儲位置。每個元素通過與前面元素鏈接和後面元素鏈接關聯,在內部保持順序。

它與 forward_list 非常相似:最大的不同在於 forward_list 是單向鏈表。單向鏈表僅能向前迭代,因此它更小更高效。

與其他基本標準順序容器(array、vector、queue)相比較,list 通常在插入、刪除和移動容器中已經獲得迭代器的任何位置的元素方面表現得更好。

list 和 forward_list 相比於其他的順序容器。主要缺點在於:它們無法通過索引直接得到元素

2. 成員函數

(1) 構造函數

通過list類內部的多種重載構造函數,我們有多種方式初始化一個list,如下所示:

#include <iostream>
#include <list>
using namespace std; 

int main ()
{
  // 1.通過幾種不同的(重載)構造函數初始化鏈表 
  list<int> first;                                // empty list of ints
  list<int> second (4,100);                       // four ints with value 100
  list<int> third (second.begin(),second.end());  // iterating through second
  list<int> fourth (third);                       // a copy of third

  // 2.迭代器可由數組創建,初始化鏈表 
  int array[] = {16,2,77,29};
  list<int> fifth (array, array + sizeof(array) / sizeof(int) );

  cout << "The contents of fifth are: ";
  for (list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)
    cout << *it << ' ';
  return 0;
}

運行結果:

The contents of fifth are: 16 2 77 29

(2) 重載運算符 =

使用重載運算符 = ,可向 list 容器分配新內容,替換其當前內容,並相應地修改其大小。如下所示:

#include <iostream>
#include <list>
using namespace std;

int main ()
{
  list<int> first (3);      // list of 3 zero-initialized ints
  list<int> second (5);     // list of 5 zero-initialized ints

  second = first;
  first = list<int>();

  std::cout << "Size of first: " << int (first.size()) <<endl;
  std::cout << "Size of second: " << int (second.size()) <<endl;
  return 0;

運行結果:

Size of first: 0
Size of second: 3

(3) 迭代器

begin || end

begin()返回指向 list 容器中的第一個元素的迭代器。end()返回指向 list 容器中的最後一個元素的迭代器。如下所示:

#include <iostream>
#include <list>
using namespace std;

int main()
{
  int array[] = {75,23,65,42,13};
  list<int> mylist(array, array+5);

  cout << "mylist contains:";
  for (list<int>::iterator it=mylist.begin(); it != mylist.end(); ++it)
    std::cout << ' ' << *it;
  return 0;
}

運行結果:

mylist contains: 75 23 65 42 13

注:與返回元素的引用的成員 list::front 不同,此函數返回指向它的雙向迭代器。

rbegin || rend

r表示reverse,即顛倒的。rbegin/rend表示list 容器的反向迭代器。

#include <iostream>
#include <list>
using namespace std;

int main ()
{
  list<int> mylist;
  for (int i=1; i<=5; ++i) 
  	mylist.push_back(i);

  cout << "mylist backwards:";
  for (list<int>::reverse_iterator rit=mylist.rbegin(); rit!=mylist.rend(); ++rit)
    cout << ' ' << *rit;
  return 0;
}

運行結果:

mylist backwards: 5 4 3 2 1

(4) Capacity

empty

empty() 判斷 list 容器是否爲空。

#include <iostream>
#include <list>
using namespace std;

int main ()
{
  list<int> mylist;
  int sum (0);

  for(int i=1;i<=10;++i) 
  	mylist.push_back(i);

  while (!mylist.empty())
  {
     sum += mylist.front();
     mylist.pop_front();
  }

  std::cout << "total: " << sum ;
  return 0;
}

運行結果:

total: 55

size || max_size

size() 返回 list 中元素的個數。
max_size 返回 list 可以容納的最大元素數。

#include <iostream>
#include <list>
using namespace std;

int main ()
{
  list<int> mylist;
 
  for (int i=0; i<10; i++) 
  	mylist.push_back(i);
  cout << "size: " << mylist.size() << endl;
  cout << "max_size: " << mylist.max_size() << endl;
  return 0;
}

運行結果:

size: 10
max_size: 357913941

(5) 訪問元素

front || back

front()返回list中的第一個元素,back()返回list中的最後一個元素。

#include <iostream>
#include <list>
using namespace std;

int main()
{
	list<int> mylist;
	for(int i=1; i<=5; ++i) 
	mylist.push_back(i);
	
	cout<<"第一個元素是:"<<mylist.front()<<endl;
	cout<<"最後一個元素是:"<<mylist.back()<<endl;
	return 0;
}

運行結果:
在這裏插入圖片描述

(6) 修改list

push_front || push_back

push_front()在原list第一個元素前添加一個數;push_back()在最後一個元素後添加一個數。

#include <iostream>
#include <list>
using namespace std;

int main ()
{
  list<int> mylist(2,100);    // two ints with a value of 100
  cout << "原始的list中各元素:";
  for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    cout << ' ' << *it;
  cout<<endl;
  
  mylist.push_front(200);
  mylist.push_front(300);

  cout << "在list前插入元素後:";
  for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    cout << ' ' << *it;
  cout <<endl;
  
  mylist.push_back(600);
  cout << "在list後插入元素後:";
  for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    cout << ' ' << *it;
  return 0;
}

運行結果:

原始的list中各元素: 100 100
在list前插入元素後: 300 200 100 100
在list後插入元素後: 300 200 100 100 600

pop_front || pop_back

pop_front():刪除list容器中的第一個元素,並將其size減1;
pop_back():刪除list容器中的最後一個元素,並將其size減1。

#include <iostream>
#include <list>
using namespace std;

int main ()
{
  list<int> mylist;
  for(int i=1;i<=5;i++)
  	mylist.push_back(i); 
  cout<<"原list中的元素:";
  for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
  	cout<<*it<<" ";
  cout<<endl;
  
  mylist.pop_front();
  cout << "刪除list開頭第一個元素後:";
  for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
  	cout<<*it<<" ";
  cout<<endl;
  cout<<"list中元素個數:"<<mylist.size()<<endl;
  
  mylist.pop_back();
  cout<<"刪除list最後一個元素:";
  for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
  	cout<<*it<<" ";
  cout<<endl;
  cout<<"list中元素個數:"<<mylist.size()<<endl;
  return 0;
}

運行結果:

原list中的元素:1 2 3 4 5
刪除list開頭第一個元素後:2 3 4 5
list中元素個數:4
刪除list最後一個元素:2 3 4
list中元素個數:3

insert

insert 在指定位置的元素之前插入新元素。

#include <iostream>
#include <list>
#include <vector>
using namespace std;

int main ()
{
  list<int> mylist;
  list<int>::iterator it;  //聲明it爲迭代器 

  for(int i=1; i<=5; ++i) mylist.push_back(i); // 1 2 3 4 5

  it = mylist.begin();
  ++it;       // it points now to number 2           ^
  mylist.insert (it,10);                        // 1 10 2 3 4 5

  // "it" still points to number 2                      ^
  mylist.insert (it,2,20);                      // 1 10 20 20 2 3 4 5

  --it;   // it points now to the second 20            ^

  std::vector<int> myvector (2,30);
  mylist.insert (it,myvector.begin(),myvector.end());   // 1 10 20 30 30 20 2 3 4 5
                                                    
  std::cout << "mylist contains:";
  for (it=mylist.begin(); it!=mylist.end(); ++it)
    cout << ' ' << *it;
  return 0;
}

運行結果:

mylist contains: 1 10 20 30 30 20 2 3 4 5

erase

erase 從 list 容器中移除單個元素元素範圍

#include <iostream>
#include <list>
using namespace std;

int main ()
{
  list<int> mylist;
  list<int>::iterator it1,it2;
  // set some values:
  for (int i=1; i<10; ++i) mylist.push_back(i*10);
                              // 10 20 30 40 50 60 70 80 90
  it1 = it2 = mylist.begin(); // ^^
  advance (it2,6);            // ^                 ^
  ++it1;                      //    ^              ^
  it1 = mylist.erase(it1);   // 10 30 40 50 60 70 80 90
                              //    ^           ^

  it2 = mylist.erase(it2);   // 10 30 40 50 60 80 90
                              //    ^           ^

  ++it1;                      //       ^        ^
  --it2;                      //       ^     ^

  mylist.erase (it1,it2);     // 10 30 60 80 90
                              //        ^
  cout << "mylist contains:";
  for (it1=mylist.begin(); it1!=mylist.end(); ++it1)
    cout << ' ' << *it1;
  return 0;
}

運行結果:

mylist contains: 10 30 60 80 90

swap

list1.swap(list2):list容器整體互換

#include <iostream>
#include <list>

int main ()
{
  std::list<int> first (3,100);   // three ints with a value of 100
  std::list<int> second (5,200);  // five ints with a value of 200

  first.swap(second);

  std::cout << "first contains:";
  for (std::list<int>::iterator it=first.begin(); it!=first.end(); it++)
    std::cout << ' ' << *it;
  std::cout << '\n';

  std::cout << "second contains:";
  for (std::list<int>::iterator it=second.begin(); it!=second.end(); it++)
    std::cout << ' ' << *it;
  return 0;
}

運行結果:

first contains: 200 200 200 200 200
second contains: 100 100 100

resize

resize():調整容器list的size大小,使其包含n個元素。
如果n小於當前容器的大小,則內容將減少到前n個元素,刪除(並銷燬它們)。
如果n大於當前容器的大小,則通過在末尾插入所需的元素來擴展內容,使其達到n的大小。如果指定了val,如list.resize(n, val) ,則將新元素初始化爲val;否則初始化爲0。

#include <iostream>
#include <list>

int main ()
{
  std::list<int> mylist;
  // set some initial content:
  for (int i=1; i<10; ++i) mylist.push_back(i); //1 2 3 4 5 6 7 8 9

  mylist.resize(5);  //1 2 3 4 5 
  mylist.resize(8,100);  //1 2 3 4 5 100 100 100
  mylist.resize(12);  //1 2 3 4 5 100 100 100 0 0 0 0

  std::cout << "mylist contains:";
  for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  return 0;
}

運行結果:

mylist contains: 1 2 3 4 5 100 100 100 0 0 0 0

clear

clear():從list容器中刪除所有元素,並將容器的size大小保留爲0。

#include <iostream>
#include <list>

int main ()
{
  std::list<int> mylist;
  std::list<int>::iterator it;

  mylist.push_back (100);
  mylist.push_back (200);
  mylist.push_back (300);

  std::cout << "mylist contains:";
  for (it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  mylist.clear(); //清空所有元素 
  mylist.push_back (1101);
  mylist.push_back (2202);

  std::cout << "mylist contains:";
  for (it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  return 0;
}

運行結果:

mylist contains: 100 200 300
mylist contains: 1101 2202

(7) Operations

remove

list.remove(val):從容器list中刪除所有與val相同的元素。並相應的減小容器的size大小。
成員函數list::erase根據元素的位置(使用迭代器)刪除元素,與之不同的是,這個函數(list::remove)根據元素的值刪除元素。

#include <iostream>
#include <list>

int main ()
{
  int myints[]= {5,6,8,8,9,45,8};
  std::list<int> mylist (myints,myints+7);

  mylist.remove(8); //刪除鏈表中所有爲8的元素 

  std::cout << "mylist contains:";
  for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  return 0;
}

運行結果:

mylist contains: 5 6 9 45

remove_if

remove_if(condition):按指定條件condition刪除list容器中的部分元素。

#include <iostream>
#include <list>

// a predicate implemented as a function:
bool single_digit (const int& value) { return (value<10); }

// a predicate implemented as a class:
struct is_odd {
  bool operator() (const int& value) { return (value%2)==1; }
};

int main ()
{
  int myints[]= {15,36,7,17,20,39,4,1};
  std::list<int> mylist (myints,myints+8);   // 15 36 7 17 20 39 4 1

  mylist.remove_if (single_digit);           // 15 36 17 20 39

  mylist.remove_if (is_odd());               // 36 20

  std::cout << "mylist contains:";
  for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  return 0;
}

運行結果:

mylist contains: 36 20

unique

版本1:list.unique():刪除容器list中相同的元素,只保留最前面的那個元素。
版本2:list.unique(condition):刪除容器list中不符合condition的元素。

#include <iostream>
#include <cmath>
#include <list>

// 判斷元素整數部分相同 
bool same_integral_part (double first, double second)
{ return ( int(first)==int(second) ); }

// 判斷相鄰元素距離是否小於5 
struct is_near {
  bool operator() (double first, double second)
  { return (fabs(first-second)<5.0); }
};

int main ()
{
  double mydoubles[]={ 12.15,  2.72, 73.0,  12.77,  3.14,
                       12.77, 73.35, 72.25, 15.3,  72.25 };
  std::list<double> mylist (mydoubles,mydoubles+10);
   
  mylist.sort();             //  2.72,  3.14, 12.15, 12.77, 12.77,
                             // 15.3,  72.25, 72.25, 73.0,  73.35
  //版本1 
  mylist.unique();           //  2.72,  3.14, 12.15, 12.77
                             // 15.3,  72.25, 73.0,  73.35
  //版本2 
  mylist.unique (same_integral_part);  //  2.72,  3.14, 12.15
                                       // 15.3,  72.25, 73.0
  
  mylist.unique (is_near());           //  2.72, 12.15, 72.25

  std::cout << "mylist contains:";
  for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  return 0;
}

運行結果:

mylist contains: 2.72 12.15 72.25

sort

版本1:list.sort():默認按ASCII碼排序
版本2:list.sort(comp):按照自定義排序規則comp進行排序

#include <iostream>
#include <list>
#include <string>
#include <cctype>

// comparison, not case sensitive.
bool compare_nocase (const std::string& first, const std::string& second)
{
  unsigned int i=0;
  while ( (i<first.length()) && (i<second.length()) )
  {
    if (tolower(first[i])<tolower(second[i])) return true;
    else if (tolower(first[i])>tolower(second[i])) return false;
    ++i;
  }
  return ( first.length() < second.length() );
}

int main ()
{
  std::list<std::string> mylist;
  std::list<std::string>::iterator it;
  mylist.push_back ("one");
  mylist.push_back ("two");
  mylist.push_back ("Three");

  mylist.sort();

  std::cout << "mylist contains:";
  for (it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  mylist.sort(compare_nocase);

  std::cout << "mylist contains:";
  for (it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

運行結果:

mylist contains: Three one two
mylist contains: one Three two

reverse

list.reverse():顛倒list容器中元素的順序

#include <iostream>
#include <list>

int main ()
{
  std::list<int> mylist;

  for (int i=1; i<10; ++i) mylist.push_back(i);

  mylist.reverse();

  std::cout << "mylist contains:";
  for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  return 0;
}

運行結果:

mylist contains: 9 8 7 6 5 4 3 2 1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章