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

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

完整版链接1: http://www.tao-studio.net/blog/index.php

链接2: http://blog.csdn.net/FocusOnACE/archive/2009/06/01/4230314.aspx

 

摘要:

本文通过示例,演示了用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 <jiangtao@tao-studio.net>

#include <iostream>
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 @<node> after @<x> in the list 0
//  success return 0,otherwise  return non-zero
int insertAfter(Node_T* header,Data_T x,Node_T* node);

//= Remove @<x> 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 :"<<endl;
	remove(header,3);
	cout<< header;

	remove(header,1);
	cout<< header;
	destroyList(header);
	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)

埋个伏笔

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
Pintos是一个操作系统的教学项目,它里面有许多基础的数据结构。其中之一就是通用链表(generic list)。 链表是一个常见的数据结构,用于存储一系列的元素。在Pintos中,通用链表是一种灵活且可扩展的数据结构,可以存储任意类型的元素。 Pintos中的通用链表由两个主要的结构组成:链表节点和链表本身。每个链表节点包含了一个指向前一个节点的指针和一个指向后一个节点的指针,以及一个用于存储元素的指针。链表本身则包含了一个指向头节点和尾节点的指针,以及用于记录链表长度的变量。 通过使用这些结构,Pintos的通用链表提供了一系列的操作来管理链表中的元素。比如,它可以实现在链表头部和尾部插入元素、删除元素以及在指定位置插入或删除元素等功能。此外,通过遍历链表,我们可以对链表中的每个元素进行操作,比如查找、更新和打印。 Pintos的通用链表使用简单而高效的方法来处理链表操作。通过使用指针连接节点,我们可以轻松地插入和删除元素,并且时间复杂度为O(1)。而遍历链表的操作也只需要O(n)的时间复杂度,其中n是链表的长度。 总之,Pintos的通用链表为操作系统的开发提供了一个方便和高效的数据结构。它可以存储任意类型的元素,并提供了丰富的操作来管理和操作这些元素。无论是在Pintos项目中还是在实际操作系统的开发中,通用链表都是一个非常有用的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值