跟我学数据结构:(3)单向链表

跟我学数据结构:(3)单向链表

摘要:

本文通过示例,演示了用C++实现数据结构的单向链表。

读者对象:

对C++有一定基础的同学。

技术要点:

C++数据抽象

构造函数

析构函数

运算符重载

编码规范初步

指针

友元

声明

本文中相关数据结构及代码是为教学需要而设计,不适用于商业产品。

链表的引入

我们在上节课“数组”是,讲到了对数据的遍历、查找、插入和删除。当我们在对数组进行插入或删除操作的时候,会引起操作点之后的元素整体移动,大量的数据移动(内存复制)会产生能下降的问题。链表正是避免了这一问题。

注:本系列教程以代码,示例演示为主,关于链表的数学定义请参考其它书籍。

链表的设计

链表一般提供了以下操作:

1) 创建链表 creatList()

2) 在指定节点后面插入一个新的节点 insertAfter()

3) 删除指定的值的节点 remove()

4) 遍历所有节点 operator<<()

5) 销毁所有链表

插入节点的操作示意图

操作前

clip_image002

操作过程

(1)

clip_image004

(2)

clip_image006

(3)

clip_image008

删除节点的操作示意图

操作前

clip_image010

操作步骤

(1)

clip_image012

(2)

clip_image014

代码及运行结果
//file: main.cpp
//desc: this program illustrate how to use linked-list
//date: 2009-6-1
//author: Stone Jiang 
  
  

#include 
 
 

  
  using 
  
  namespace std;


  
  typedef  
  
  int  Data_T;

  
  class Node_T
{

  
  public:
	
  
  // [1]
	
  
  explicit Node_T(Data_T x);
	Node_T();
	~Node_T();

  
  public:
	
  
  // public interface
	
  
  void next(Node_T* next);
	Node_T* next(
  
  void);
	Data_T value();
    
  
  // [2]
	
  
  friend ostream& 
  
  operator << (ostream& os, Node_T* header);

  
  private:
    Data_T value_;
	Node_T* next_;
};


Node_T::Node_T()
:value_(0),next_(0)
{
	
  
  //cout << " create " << this->value_ << endl;

}

Node_T::Node_T(Data_T x)
:value_(x),next_(0)
{
	
  
  //cout << " create " << this->value_ << endl;

}

Data_T Node_T::value()
{
	
  
  return 
  
  this->value_;
}

Node_T::~Node_T()
{
	
  
  //cout << " destroy " << this->value_ << endl;
}


  
  void Node_T::next(Node_T* next)
{
	
  
  this->next_ = next;
}

Node_T* Node_T::next()
{
	
  
  return 
  
  this->next_;
}



  
  //= create List
Node_T*  createList();


  
  //= Insert a new node @
   
   
    
     after @
    
    
     
      in the list 0
    
    
   
   

  
  //  success return 0,otherwise  return non-zero

  
  int insertAfter(Node_T* header,Data_T x,Node_T* node);


  
  //= Remove @
   
   
    
     from list
   
   

  
  int remove(Node_T* header,Data_T x);


  
  //= destroyList

  
  int destroyList(Node_T* header);

ostream& 
  
  operator << (ostream& os, Node_T* header);


  
  int main(
  
  int, 
  
  char**)
{

	Node_T* header = createList();
	cout << header;
	Node_T* one  = 
  
  new Node_T(1);
	insertAfter(header,0,one);
    cout << header;

	Node_T* three = 
  
  new Node_T(3);
	insertAfter(header,1,three);
	cout << header;

	Node_T* two = 
  
  new Node_T(2);
	insertAfter(header,1,two);
	cout << header;

	Node_T* five = 
  
  new Node_T(5);
	insertAfter(header,3,five);
	cout << header;

	cout << "
  
  remove :"<
  
  
   
   return 0;
}


Node_T* createList()
{
	Node_T* header = 
   
   new Node_T(0);
	
   
   return header;
}


   
   int insertAfter(Node_T* header,Data_T x,Node_T* node)
{
	
   
   int result = -1;
	
   
   if (header)
	{
		Node_T* current = header;
		
   
   if (current->value() == x || current->next() == 0)
		{
			
   
   // [1]
			node->next(current->next());
			current->next(node);
			result = 0;
		}
		
   
   else
		{
			
   
   return insertAfter(current->next(),x,node);
		}
	}

	
   
   return result;
}


   
   int remove(Node_T* header,Data_T x)
{
	
   
   int result = -1;

	
   
   if (header)
	{
		Node_T* prev = header;
		Node_T* current = header->next();
		
   
   if (current->value() == x)
		{
			prev->next(current->next());
			
   
   delete current;
			current  = 0;
			result = 0;
		}
		
   
   else
		{
			
   
   return remove(current,x);
		}
	}
	
   
   return result;
}


   
   int destroyList(Node_T* header)
{

	Node_T* current = header;
	
   
   while (current)
	{
		Node_T* temp = current;
		current = current->next();
		
   
   delete temp;
		temp = 0;
	}

	
   
   return 0;
}

ostream& 
   
   operator << (ostream& os,  Node_T* header)
{
	
   
   if (header)
	{
		Node_T* current = header;
		os << "
   
   ( " << current->value() << "
   
    ) ---> ";
		
		
   
   return  os << current->next();
	}
	
   
   else
	{
		cout << "
   
    ( END )" << endl;
	}

	
   
   return os;

}
  
  
 
 

 

( 0 ) --->  ( END )
( 0 ) ---> ( 1 ) --->  ( END )
( 0 ) ---> ( 1 ) ---> ( 3 ) --->  ( END )
( 0 ) ---> ( 1 ) ---> ( 2 ) ---> ( 3 ) --->  ( END )
( 0 ) ---> ( 1 ) ---> ( 2 ) ---> ( 3 ) ---> ( 5 ) --->  ( END )
remove :
( 0 ) ---> ( 1 ) ---> ( 2 ) ---> ( 5 ) --->  ( END )
( 0 ) ---> ( 2 ) ---> ( 5 ) --->  ( END )
代码说明

(1) 部分收入C++面向对象的特性。示例中演示了构造函数,重载了构造函数。

(2) 代码中使用了递归算法。由于链表的定义可以通过递归来定义,并且在之后的课程中我们将广泛的使用递归算法,所以,我们在本代码中使用了递归算法。

您能找出我们在哪些地方用到了递归吗?

(3) 重载 << 函数。 为了方便对链表的遍历和输入,我们重载了< <函数。同学们是否可以从main()中看到,使用了> <<()之后,代码变简洁了?

(4)

埋个伏笔

我们并没有对链表作完合的面向对象封装,所以在使用代码的时候,额外的增加了对链表是否有效作了判断。另外,为了使代码简洁,我们并对函数调用的返回值作检查。在创建和删除节点的时候,我们都使用了动态内存分配。如果我们插入从栈上的临时节点到链表中,将收内存问题。这些,我们都将在后续的课程中为大家解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值