链表总结----基本知识

             这里主要介绍链表的基本知识,加深对链表的了解,以及关于链表的常见的面试题。

    一、链表基础知识

         1.概念
        链表是一种物理存储结构上非连续/非顺序的存储结构。链表的每个结点里面存储着下一个结点的指针,把存储数据元素的数据串链起来。
2.结点组成 
        数据域:存储数据元素
        指针域:存储下一个结点地址的指针域  
3.分类
        单链表:是一种逻辑上的线性结构,只有一条链,首尾不相连,方向不会改变。
        双向链表:指针域有两个指针,分别指向它的前驱结点和后继个结点。
        循环链表:尾结点的指针域的指针指向头结点(头尾相连形成一个环形结构) 
4.优缺点
    优点:
    1.创建结点:克服预先知道数据大小的缺点,充分利用计算机空间,实现灵活的内存动态管理。
    2.删除结点:删除结点时只需要修改结点的指针域,不需要将其他数据向前移动。
        注:优缺点一般是相对于顺序存储。
    缺点:
    1.访问结点:通过循环或递归访问到链表的数据,访问效率低于线性数据结构。
    2、存储方面:增加结点的指针域,空间开销比较大。
二、链表的实现
          1.单链表   
              单链表结构

                  插入结点 
        


Node* BuyNode(DataType x)
{
    Node* node = (Node* )malloc(sizeof(Node));
	node->data  = x;
	node->next = NULL;
	return node;
}
void PushFront(Node** pphead, DataType x)
{
	if(*pphead == NULL)
	{
		*pphead = BuyNode (x);
	}
	else
	{
		Node* node = BuyNode(x);
		node->next = *pphead;
		*pphead = node;
	}
}
void Insert(Node** pphead,Node* pos,DataType x)
{
	assert(pos);
	if(*pphead == pos)//头插
	{
		PushFront(pphead,x);
	}
	else
	{
		Node* prev = *pphead ;
		Node* tmp = BuyNode(x);
		while(prev->next != pos)
		{
			prev = prev->next ;
		} 
		tmp ->next = pos;
		prev->next = tmp;
	}
}

        删除结点

void Erase(Node** pphead,Node* pos)
{
	assert(pos);
	if(*pphead == pos)
	{
		PopFront (pphead);
	}
	else
	{
		Node* cur = *pphead;
		while(cur->next != pos)
		{
			cur = cur->next;
		}
		cur->next = pos->next;
		free(pos);
	}
}

             2.双向链表          

            插入结点
        
void List::Insert(Node* pos,const DataType& x)
{
	//空链表、一个结点、一般情况
	Node* NewNode = new Node(x);
	if(_head == pos)
	{
		if(_head == NULL)
		{
			_head = _tail = NewNode;
		}
		else
		{
			NewNode->_next = _head;
			_head->_prev = NewNode;
			_head = NewNode;
		}
	}
	else 
	{
		Node* prev = pos->_prev ;
		prev->_next = NewNode;
		NewNode->_prev = prev;
		NewNode->_next = pos;
		pos->_prev = NewNode;
	}
}

 
 

        删除结点
    
void List::Erase(Node* pos)
{
	//头删、尾删、一般情况、NULL、一个结点
	if(_head == _tail)//一个结点
	{
		assert(_head);
		_head = _tail = NULL;
	}
	else if(pos == _head)//头删
	{
		_head = _head ->_next ;
		_head ->_prev = NULL;
	}
	else if(pos == _tail)//尾删
	{
		Node* tmp = _tail->_prev ;
		tmp->_next = NULL;
		_tail = tmp;
	}
	else //一般情况
	{
		Node* prev = pos->_prev ;
		Node* next = pos->_next ;
		prev->_next = next;
		next->_prev = prev;
	}
	delete pos;
}

 
 

             3.双向循环链表
        
                插入结点&删除结点
List()
		:_head(new Node(T()))
	{
		_head->_prev = _head;
		_head->_next = _head;
	}

template<class T>
void List<T>::Insert(Node* pos, const T& x)
{
	assert(pos);
	Node* newNode = new Node(x);
	Node* prev = pos->_prev;

	prev->_next = newNode;
	newNode->_prev = prev;
	newNode->_next = pos;
	pos->_prev = newNode;
}

template<class T>
void List<T>::Erase(Node* pos)
{
	assert(pos && pos != _head);

	Node* prev = pos->_prev ;
	Node* next = pos->_next ;

	delete pos;

	prev->_next = next;
	next->_prev = prev;
}

         三、STL中List
                 1.各接口
                 2.迭代器失效问题
                     3.实现(迭代器实现)
template<class T, class Ref, class Ptr>  //通过实例化的类型不同,实现不同的迭代器
struct _ListIterator  
{
	typedef _ListIterator<T,Ref, Ptr> Self;
	typedef ListNode<T> Node;
	Node* _node;

	_ListIterator(Node* node) //构造函数
		:_node(node)
	{}

	Ref operator* () //*操作符重载
	{
		return _node->_data;
	}

	Self& operator++()  //后置++
	{
		_node = _node->_next;
		return *this; 
	}

	Self operator++(int)//前置++
	{
		Self tmp(*this);
		_node = _node->_next;
		return tmp; //返回的是临时变量的值,所以用Self
	}

	Self& operator--() //后置--
	{
		_node = _node->_prev;
		return *this;
	}

	Self operator--(int) //前置--
	{
		Self tmp(*this);

		_node = _node->_prev;
		return tmp;
	}

	bool operator != (const Self&s )
	{
		return _node != s._node;
	}

	bool operator == (const Self&s)
	{
		return _node == s->_node;
	}
	
	Ptr operator->()
	{
		return &(_node->_data); //当指向结构体时,具有 -> 作用
	}

};

        总结:从单链表到双向循环链表,可以发现双向循环链表简化增加和删除操作,具体使用哪种链表还依情况而定。对于STL中的list可以说极大的方面了用户操作,迭代器也很好的实现了封装。

本文只是对链表的简单介绍,有关错误欢迎指出。
有关于链表的具体实现详见: https://github.com/zwjuan/List

猜你喜欢

转载自blog.csdn.net/smile_zhangw/article/details/80202668
今日推荐