List
双向链表
每一个结点都包括一个信息快Info、一个前驱指针Pre、一个后驱指针Post。可以不分配必须的内存大小方便的进行添加和删除操作。使用的是非连续的内存空间进行存储。
优点:(1) 不使用连续内存完成动态操作。
(2) 在内部方便的进行插入和删除操作
(3) 可在两端进行push、pop
缺点:(1) 不能进行内部的随机访问,即不支持[ ]操作符和vector.at()
(2) 相对于verctor占用内存多
测试目的:
(1) 熟悉了解STL List基本使用方法;
(2) 熟悉函数特性,合理高效使用标准函数;
(3) 使用标准:尽可能使用标准函数,高效使用interator,泛型编程思想;
#include <iostream>
#include <list>
#include <ctime>
#include <cstdio>
#include <windows.h>
using namespace std;
//
//STL List Test
typedef list<int> IntList;
class IntListTest
{
public:
IntListTest():MAX_LIST_SIZE(10) { InitIntList(); }
~IntListTest(){};
//assign() test
/*************************************************************************************
* void assign( input_iterator start, input_iterator end );
* void assign( size_type num, const TYPE &val );
* assign()函数以迭代器start和end指示的范围为list赋值或者为list赋值num个以val为值的元素。
*************************************************************************************/
void assign_Test1();
void assign_Test2();
void assign_performance_test();
//back() test
/*************************************************************************************
* reference back();
* back()函数返回一个引用,指向list的最后一个元素。
*************************************************************************************/
void back_test();
//clear() and empty() test
/*************************************************************************************
* void clear();
* clear()函数删除list的所有元素
---
* bool empty();
* empty()函数返回真(true)如果链表为空,否则返回假
*************************************************************************************/
void clear_empty_test();
//erase() test;
/*************************************************************************************
* iterator erase( iterator pos );
* iterator erase( iterator start, iterator end );
* erase()函数删除以pos指示位置的元素, 或者删除start和end之间的元素。 返回值是一个迭代器,
* 指向最后一个被删除元素的下一个元素。
*************************************************************************************/
void erase_test();
//front() test
/*************************************************************************************
* reference front();
* front()函数返回一个引用,指向链表的第一个元素。
*************************************************************************************/
void front_test();
//get_allocator() test
/*
* allocator_type get_allocator();
* get_allocator()函数返回链表的配置器。
*/
void get_allocator_test();//?????????
//insert() test1
/*************************************************************************************
* iterator insert( iterator pos, const TYPE &val );
* void insert( iterator pos, size_type num, const TYPE &val );
* void insert( iterator pos, input_iterator start, input_iterator end );
* insert()插入元素val到位置pos,或者插入num个元素val到pos之前,或者插入start到end之间的元素到pos的
* 位置。返回值是一个迭代器,指向被插入的元素。
*************************************************************************************/
void insert_test1();
void insert_test2();
void insert_test3();
void insert_performance_test();
//
/*************************************************************************************
* size_type max_size();
* max_size()函数返回链表能够储存的元素数目。
*************************************************************************************/
void max_size_test();
//
/*
* void merge( list &lst );
* void merge( list &lst, Comp compfunction );
* merge()函数把自己和lst链表连接在一起,产生一个整齐排列的组合链表。如果指定compfunction,则将指定函数作为比较的依据。
*/
void merge_test();//???
IntList& merge_compfunction(IntList& l1);
typedef void(*cmpfun)(IntList& l1);
//
/*
* void remove( const TYPE &val );
* remove()函数删除链表中所有值为val的元素
*/
void remove_test();
/*
* void remove_if( UnPred pr );
* remove_if()以一元谓词pr为判断元素的依据,遍历整个链表。如果pr返回true则删除该元素。
*/
void remove_if_test();
//
/*
* void resize( size_type num, TYPE val );
* resize()函数把list的大小改变到num。被加入的多余的元素都被赋值为val
*/
void resize_test();
//
/*
* void reverse();
* reverse()函数把list所有元素倒转。
*/
void reverse_test();
//
/*
* void sort();
* void sort( Comp compfunction );
* sort()函数为链表排序,默认是升序。如果指定compfunction的话,就采用指定函数来判定两个元素的大小。
*/
void sort_test1();
void sort_test2();
//
/*
* void splice( iterator pos, list &lst );
* void splice( iterator pos, list &lst, iterator del );
* void splice( iterator pos, list &lst, iterator start, iterator end );
* splice()函数把lst连接到pos的位置。如果指定其他参数,则插入lst中del所指元素到现链表的pos上,或者用start和end指定范围。
*/
void splice_test1();
void splice_test2();
void splice_test3();
//
/*
* void swap( list &lst );
* swap()函数交换lst和现链表中的元素。
*/
void swap_test();
//
/*
* void unique();
* void unique( BinPred pr );
* unique()函数删除链表中所有重复的元素。如果指定pr,则使用pr来判定是否删除
*/
void unique_test();
private:
void InitIntList();
bool CheckList(const IntList& list1, const IntList& list2);
void ShowDiffTime();
void ShowDiffTime2();
void StartTime();
void EndTime();
private:
const size_t MAX_LIST_SIZE;
IntList intList1;
IntList intList2;
time_t startTime;
time_t finishTime;
SYSTEMTIME sysStartTime;
SYSTEMTIME sysEndTime;
};
//implement
void IntListTest::InitIntList()
{
intList1.clear();
intList2.clear();
for (size_t i = 0; i != MAX_LIST_SIZE; ++i)
{
intList1.push_back(i);
intList2.push_back(i);
}
return;
}
bool IntListTest::CheckList(const IntList& list1, const IntList& list2)
{
if ( list1.size()!=list2.size()
|| list1.size()==0
|| list2.size()==0 )
{
return false;
}
IntList::const_iterator itr1 = list1.begin(),itr2 =list2.begin();
IntList::const_iterator end1 = list1.end(),end2 =list2.end();
for (size_t i = 0; (i!=MAX_LIST_SIZE) && (itr1!=end1) && (itr2!=end2); ++i,++itr1,++itr2)
{
if (*itr1 != *itr2)
{
return false;
}
}
return true;
}
void IntListTest::ShowDiffTime()
{
time_t elapsed_time = finishTime - startTime;
printf("Program takes %6.6d seconds./n", elapsed_time);
ShowDiffTime2();
return;
}
void IntListTest::ShowDiffTime2()
{
SYSTEMTIME Time ;
Time.wMinute = sysEndTime.wMinute - sysStartTime.wMinute;
Time.wSecond = sysEndTime.wSecond - sysStartTime.wSecond;
Time.wMilliseconds = sysEndTime.wMilliseconds - sysStartTime.wMilliseconds;
printf("Program takes --%2d Minutes %2d Seconds %6d Milliseconds./n",
Time.wMinute,
Time.wSecond,
Time.wMilliseconds);
return;
}
void IntListTest::StartTime()
{
time(&startTime);
GetSystemTime(&sysStartTime);
}
void IntListTest::EndTime()
{
time(&finishTime);
GetSystemTime(&sysEndTime);
}
void IntListTest::assign_Test1()
{
intList2.clear();
if (intList2.size() > 0 )
{
cout<<"[assign_Test1]:intList2 is not empty! /n";
return;
}
else
{
intList2.assign(intList1.begin(), intList1.end());
if (!CheckList(intList1, intList2))
{
cout<<"[assign_Test1]:intList1 not equals intList2! /n";
return;
}
}
}
void IntListTest::assign_Test2()
{
intList1.clear();
intList2.clear();
const int INT_ITEM = 100;
for (size_t i = 0; i!= MAX_LIST_SIZE; ++i)
{
intList1.push_back(INT_ITEM);
}
if (intList1.size() != MAX_LIST_SIZE)
{
cout<<"[assign_Test2]:intList1's size not equals "<<MAX_LIST_SIZE<<"! /n";
return;
}
else if (intList2.size() > 0 )
{
cout<<"[assign_Test2]:intList2 is not empty! /n";
return;
}
else
{
intList2.assign(MAX_LIST_SIZE, INT_ITEM);
if (!CheckList(intList1, intList2))
{
cout<<"[assign_Test2]:intList1 not equals intList2! /n";
return;
}
}
}
void IntListTest::assign_performance_test()
{
const size_t TOTAL_TEST_TIMES = 500000;
const int LIST_ITEM = 0;
//
//test1
intList1.clear();
StartTime();
for (size_t i = 0 ; i != TOTAL_TEST_TIMES; ++i)
{
intList1.push_back(LIST_ITEM);
}
EndTime();
ShowDiffTime();
//
//test 2
intList2.clear();
StartTime();
for (IntList::const_iterator itr = intList1.begin(), e=intList1.end(); itr != e; ++itr)
{
intList2.push_back(*itr);
}
EndTime();
ShowDiffTime();
if (!CheckList(intList1, intList2))
{
cout<<"[assign_performance_test]:intList1 not equals intList2! /n";
return;
}
//
//test 3
intList2.clear();
StartTime();
intList2.assign(TOTAL_TEST_TIMES, LIST_ITEM);
EndTime();
ShowDiffTime();
if (!CheckList(intList1, intList2))
{
cout<<"[assign_performance_test]:intList1 not equals intList2! /n";
return;
}
//
//test 4
intList2.clear();
if (intList2.size() != 0)
{
cout<<"[assign_performance_test]:intList3 is not empty! /n";
return;
}
StartTime();
intList2.assign(intList1.begin(), intList1.end());
EndTime();
ShowDiffTime();
if (!CheckList(intList1, intList2))
{
cout<<"[assign_performance_test]:intList1 not equals intList2! /n";
return;
}
}
void IntListTest::back_test()
{
InitIntList();
int member = static_cast<int> (MAX_LIST_SIZE-1);
while ( intList1.size() != 0)
{
if ( intList1.back() == member)
{
intList1.pop_back();
// IntList::iterator pos = intList1.end();
// intList1.erase(pos);
member--;
continue;
}
else
{
cout<<"[back_test]:Member doesn't matched! /n";
return;
}
}
return;
}
void IntListTest::clear_empty_test()
{
intList1.clear();
intList2.clear();
if (!intList1.empty())
{
cout<<"[clear_empty_test]:intList1 is not empty!/n";
return;
}
else if (!intList2.empty())
{
cout<<"[clear_empty_test]:intList2 is not empty!/n";
return;
}
InitIntList();
if (intList1.empty())
{
cout<<"[clear_empty_test]:intList1 is empty!/n";
return;
}
else if (intList2.empty())
{
cout<<"[clear_empty_test]:intList2 is empty!/n";
return;
}
return;
}
void IntListTest::erase_test()
{
InitIntList();
size_t listSize = 0;
while ( (listSize=intList1.size()) != 0 )
{
intList1.erase(intList1.begin());
if ( listSize != (intList1.size()+1) )
{
cout<<"[erase_test]:erase data failed!/n";
return;
}
//invalid usage
//intList1.erase(intList1.end());
}
return;
}
void IntListTest::front_test()
{
InitIntList();
for (size_t i = 0; i != MAX_LIST_SIZE-1; i++)
{
if ( intList1.front() == static_cast<int>(i) )
{
intList1.erase(intList1.begin());
continue;
}
else
{
cout<<"[front_test]:get front failed! /n";
break;
}
}
}
void IntListTest::get_allocator_test()
{
//Returns a copy of the allocator object used to construct a list.
// Allocator get_allocator( ) const;
//
// // list_get_allocator.cpp
// // compile with: /EHsc
// #include <list>
// #include <iostream>
//
// int main( )
// {
// using namespace std;
// // The following lines declare objects
// // that use the default allocator.
intList1.clear();
intList2.clear();
list <int> c1;
const int MAX_INT_SIZE = 100;
for (int i =0; i<MAX_INT_SIZE; i++)
{
intList1.push_back(i);
}
IntList intList3(intList1.get_allocator());//????????????????????????????????
if (intList3.size() == 0)
{
return;
}
for (IntList::const_iterator itr = intList3.begin(),e=intList3.end(); itr!=e; ++itr)
{
int item = *itr;
continue;
}
list <int, allocator<int> > c2 = list <int, allocator<int> >( allocator<int>( ) );
// c3 will use the same allocator class as c1
list <int> c3( c1.get_allocator( ) );
list<int>::allocator_type xlst = c1.get_allocator( );
// You can now call functions on the allocator class used by c1
// }
}
//insert()插入元素val到位置pos
void IntListTest::insert_test1()
{
InitIntList();
intList1.insert(intList1.end(), static_cast<int>(MAX_LIST_SIZE));
intList1.insert(intList1.end(), static_cast<int>(MAX_LIST_SIZE+1));
intList1.insert(intList1.end(), static_cast<int>(MAX_LIST_SIZE+2));
int pos = 0;
for (IntList::const_iterator itr=intList1.begin(), e=intList1.end(); itr!=e; ++itr,pos++)
{
if (*itr != pos)
{
cout<<"[insert_test1]:insert element failed! /n";
return ;
}
}
return;
}
//插入num个元素val到pos之前
void IntListTest::insert_test2()
{
InitIntList();
int number = 3;
const int item = 10;
intList1.insert(intList1.begin(), number, item);
for (int i = 0; i<number; i++)
{
if ( intList1.front() == item
&& intList1.size() == (MAX_LIST_SIZE+number-i) )
{
intList1.pop_front();
}
else
{
cout<<"[insert_test2]:insert_test2 test failed!/n";
return;
}
}
return;
}
//插入start到end之间的元素到pos的位置
void IntListTest::insert_test3()
{
InitIntList();
intList1.insert(intList1.end(), intList2.begin(), intList2.end());
if (intList1.size() != MAX_LIST_SIZE*2)
{
cout<<"[insert_test2]:Insert member failed! /n";
return;
}
int item = 0;
for (IntList::const_iterator itr = intList1.begin(),e=intList1.end(); itr!=e; ++itr)
{
if (*itr != item++)
{
cout<<"[insert_test2]:Insert member failed! /n";
return;
}
if (item == MAX_LIST_SIZE)
{
item = 0;
}
}
return;
}
void IntListTest::insert_performance_test()
{
intList1.clear();
intList2.clear();
const int TEST_SIZE = 5000000;
StartTime();
for (int i = 0 ; i < TEST_SIZE; i++)
{
intList1.insert(intList1.end(), i);
}
EndTime();
ShowDiffTime();
StartTime();
for (int i = 0 ; i < TEST_SIZE; i++)
{
intList2.push_back(i);
}
EndTime();
ShowDiffTime();
StartTime();
for (IntList::const_iterator itr = intList1.begin(); itr!=intList1.end(); ++itr)
{;}
EndTime();
ShowDiffTime();
StartTime();
for (IntList::const_iterator itr = intList1.begin(), e=intList1.end(); itr!=e; ++itr)
{;}
EndTime();
ShowDiffTime();
return;
}
void IntListTest::max_size_test()
{
InitIntList();
size_t maxSzie = intList1.max_size();
maxSzie = intList2.max_size();
return;
}
IntList& merge_compfunction(IntList& l1)
{
return l1;
}
void IntListTest::merge_test()
{
InitIntList();
intList1.merge(intList2);
size_t member = 0;
if (intList1.size() != MAX_LIST_SIZE*2)
{
cout<<"Merge failed!/n";
return;
}
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr)
{
member = *itr;
cout<< member<<"/n";
}
member = intList2.size();
for (IntList::const_iterator itr=intList2.begin(),e=intList2.end(); itr!=e; ++itr)
{
member = *itr;
}
//intList1.merge(intList2, &cmpfun);
return;
}
//remove()函数删除链表中所有值为val的元素
void IntListTest::remove_test()
{
InitIntList();
if ( intList1.size()!=MAX_LIST_SIZE
|| intList2.size()!=MAX_LIST_SIZE)
{
cout<<"[remove_test]:intList size err!/n";
}
intList1.remove(0);
intList2.remove(MAX_LIST_SIZE-1);
int item =1;
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,++item)
{
if (*itr != item)
{
cout<<"[remove_test]:intList1 member err!/n";
return;
}
}
item = 0;
for (IntList::const_iterator itr=intList2.begin(),e=intList2.end(); itr!=e; ++itr,++item)
{
if (*itr != item)
{
cout<<"[remove_test]:intList2 member err!/n";
return;
}
}
return;
}
bool find_list_member1(int& value )
{
if (value==0 )
{
return true;
}
return false;
}
bool find_list_member2(int& value /*value type of list*/)
{
if (value==9/*MAX_LIST_SIZE-1*/)
{
return true;
}
return false;
}
//remove_if()以一元谓词pr为判断元素的依据,遍历整个链表。如果pr返回true则删除该元素。
void IntListTest::remove_if_test()
{
InitIntList();
if ( intList1.size()!=MAX_LIST_SIZE
|| intList2.size()!=MAX_LIST_SIZE)
{
cout<<"[remove_if_test]:intList size err!/n";
}
intList1.remove_if(find_list_member1);
intList2.remove_if(find_list_member2);
int item =1;
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,++item)
{
if (*itr != item)
{
cout<<"[remove_if_test]:intList1 member err!/n";
return;
}
}
item = 0;
for (IntList::const_iterator itr=intList2.begin(),e=intList2.end(); itr!=e; ++itr,++item)
{
if (*itr != item)
{
cout<<"[remove_if_test]:intList2 member err!/n";
return;
}
}
return;
}
//resize()函数把list的大小改变到num。被加入的多余的元素都被赋值为val
void IntListTest::resize_test()
{
InitIntList();
//step 1
int item = 0 ;
const int TEST_SIZE = 5;
if ( intList1.size() != MAX_LIST_SIZE )
{
cout<<"[resize_test]:intList1 size err(step 1)!/n";
}
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,item++)
{
if (*itr != item)
{
cout<<"[resize_test]:intList1 member err(step 1)!/n";
return;
}
}
//step 2
intList1.resize(TEST_SIZE, 100);
item = 0 ;
if ( intList1.size() != TEST_SIZE )
{
cout<<"[resize_test]:intList1 size err(step 2)!/n";
}
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,item++)
{
if (*itr != item)
{
cout<<"[resize_test]:intList1 member err(step 2)!/n";
return;
}
}
//setp 3
intList1.resize(TEST_SIZE*2, 100);
item = 0 ;
if ( intList1.size() != 10 )
{
cout<<"[resize_test]:intList1 size err(step 3)!/n";
}
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,item++)
{
if (*itr != (item>TEST_SIZE-1 ? 100:item))
{
cout<<"[resize_test]:intList1 member err(step 3)!/n";
return;
}
}
return;
}
//reverse()函数把list所有元素倒转。
void IntListTest::reverse_test()
{
InitIntList();
intList1.reverse();
int item = MAX_LIST_SIZE-1 ;
if ( intList1.size() != MAX_LIST_SIZE )
{
cout<<"[resize_test]:intList1 size err(step 1)!/n";
}
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,item--)
{
if (*itr != item)
{
cout<<"[reverse_test]:intList1 member err!/n";
return;
}
}
return;
}
void IntListTest::sort_test1()
{
intList1.clear();
intList1.push_back(2);
intList1.push_back(0);
intList1.push_back(1);
intList1.push_back(4);
intList1.push_back(3);
intList1.sort();
int item = 0 ;
if ( intList1.size() != 5 )
{
cout<<"[sort_test1]:intList1 size err(step 1)!/n";
}
for (IntList::const_iterator itr=intList1.begin(), e=intList1.end(); itr!=e; ++itr,item++)
{
if (*itr != item)
{
cout<<"[sort_test1]:intList1 member err!/n";
return;
}
}
return;
}
void IntListTest::sort_test2()
{
//void sort( Comp compfunction );
return;
}
//splice()函数把lst连接到pos的位置。如果指定其他参数,则插入lst中del所指元素到现链表的pos上,或者用start和end指定范围。
void IntListTest::splice_test1()
{
InitIntList();
intList1.clear();
if ( intList1.size() != 0 )
{
cout<<"[splice_test1]:intList1 size is not empty!/n";
}
int item = 0 ;
intList1.splice(intList1.end(), intList2);// void splice( iterator pos, list &lst );
if ( intList1.size() != MAX_LIST_SIZE )
{
cout<<"[splice_test1]:intList1 size err!/n";
}
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,item++)
{
if (*itr != item)
{
cout<<"[splice_test1]:intList1 member err!/n";
return;
}
}
return;
}
void IntListTest::splice_test2()
{
InitIntList();
intList1.clear();
if ( intList1.size() != 0 )
{
cout<<"[splice_test2]:intList1 size is not empty!/n";
}
int item = 5 ;
IntList::iterator pos = intList2.begin();
for (int i = 0; i < 5; i++)
{
++pos;
}
intList1.splice(intList1.end(), intList2, pos); //void splice( iterator pos, list &lst, iterator del );
if ( intList1.size() != 1 )
{
cout<<"[splice_test2]:intList1 size err!/n";
return;
}
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr)
{
if (*itr != item)
{
cout<<"[splice_test2]:intList1 member err!/n";
return;
}
}
return;
}
void IntListTest::splice_test3()
{
InitIntList();
intList1.clear();
if ( intList1.size() != 0 )
{
cout<<"[splice_test3]:intList1 size is not empty!/n";
}
int item = 5 ;
IntList::iterator pos = intList2.begin();
for (int i = 0; i < 5; i++)
{
++pos;
}
intList1.splice(intList1.end(), intList2, pos, intList2.end());
//void splice( iterator pos, list &lst, iterator start, iterator end );
if ( intList1.size() != 5 )
{
cout<<"[splice_test3]:intList1 size err!/n";
return;
}
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,item++)
{
if (*itr != item)
{
cout<<"[splice_test3]:intList1 member err!/n";
return;
}
}
return;
}
void IntListTest::swap_test()
{
InitIntList();
intList1.clear();
intList1.swap(intList2);
if (intList2.size() != 0)
{
cout<<"[swap_test]:intList2 size is not empty!/n";
return;
}
else if (intList1.size()!=MAX_LIST_SIZE)
{
cout<<"[swap_test]:intList1 size err!/n";
return;
}
int item = 0;
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,item++)
{
if (*itr != item)
{
cout<<"[swap_test]:intList1 member err!/n";
return;
}
}
return;
}
void IntListTest::unique_test()
{
InitIntList();
intList1.splice(intList1.end(), intList2);
if (intList1.size() != 2*MAX_LIST_SIZE)
{
cout<<"[unique_test]:intList1 size is err!/n";
return;
}
intList1.unique();
intList1.sort();
if (intList1.size() != MAX_LIST_SIZE)
{
cout<<"[unique_test]:intList1 size is err!/n";
return;
}
int item = 0;
for (IntList::const_iterator itr=intList1.begin(),e=intList1.end(); itr!=e; ++itr,item++)
{
if (*itr != item)
{
cout<<"[unique_test]:intList1 member err!/n";
return;
}
}
return;
}
//
void main()
{
IntListTest test1;
// test1.assign_Test1();
// test1.assign_Test2();
// test1.assign_performance_test();
// test1.back_test();
// test1.clear_empty_test();
// test1.erase_test();
// test1.front_test();
// test1.get_allocator_test();
// test1.insert_test1();
// test1.insert_test2();
// test1.insert_test3();
// test1.insert_performance_test();
// test1.max_size_test();
// test1.merge_test();
// test1.remove_test();
// test1.remove_if_test();
// test1.resize_test();
// test1.resize_test();
// test1.reverse_test();
// test1.sort_test1();
// test1.splice_test1();
// test1.splice_test2();
// test1.splice_test3();
test1.swap_test();
test1.unique_test();
}