知识大全 数据结构学习讲座(C++) 单链表(1)
Posted 函数
篇首语:丈夫清万里,谁能扫一室?本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 数据结构学习讲座(C++) 单链表(1)相关的知识,希望对你有一定的参考价值。
数据结构学习讲座(C++) 单链表(1) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
单链表( ) 节点类
#ifndef Node_H #define Node_H
template <class Type> class Node //单链节点类 public: Type data; Node<Type> *link; Node() : data(Type()) link(NULL) Node(const Type &item) : data(item) link(NULL) Node(const Type &item Node<Type> *p) : data(item) link(p) ;#endif 【说明】因为数据结构里用到这个结构的地方太多了 如果用《数据结构》那种声明友元的做法 那声明不知道要比这个类的本身长多少 不如开放成员 事实上 这种结构只是C中的struct 除了为了方便初始化一下 不需要任何的方法 原书那是画蛇添足 下面可以看到 链表的public部分没有返回Node或者Node*的函数 所以 别的类不可能用这个开放的接口对链表中的节点操作
【重要修改】原书的缺省构造函数是这样的Node() : data(NULL) link(NULL) 我原来也是照着写的 结果当我做扩充时发现这样是不对的 当Type为结构而不是简单类型(int ……) 不能简单赋NULL值 这样做使得定义的模板只能用于很少的简单类型 显然 这里应该调用Type的缺省构造函数 这也要求 用在这里的类一定要有缺省构造函数 在下面可以看到构造链表时 使用了这个缺省构造函数 当然 这里是约定带表头节点的链表 不带头节点的情况请大家自己思考
【闲话】请不要对int *p = new int( );这种语法有什么怀疑 实际上int也可以看成一种class
单链表类定义与实现
#ifndef List_H#define List_H#ifndef TURE #define TURE #endif#ifndef FALSE #define FALSE #endif
typedef int BOOL;
#include Node h
template <class Type> class List //单链表定义 //基本上无参数的成员函数操作的都是当前节点 即current指的节点 //认为表中 第 个节点 是第 个节点 请注意 即表长为 时 最后一个节点是第 个节点 public: List() first = current = last = new Node<Type>; prior = NULL; ~List() MakeEmpty(); delete first; void MakeEmpty() //置空表 Node<Type> *q; while (first >link != NULL) q = first >link; first >link = q >link; delete q; Initialize(); BOOL IsEmpty() if (first >link == NULL) Initialize(); return TURE; else return FALSE; int Length() const //计算带表头节点的单链表长度 Node<Type> *p = first >link; int count = ; while (p != NULL) p = p >link; count++; return count; Type *Get()//返回当前节点的数据域的地址 if (current != NULL) return ¤t >data; else return NULL; BOOL Put(Type const &value)//改变当前节点的data 使其为value if (current != NULL) current >data = value; return TURE; else return FALSE;
Type *GetNext()//返回当前节点的下一个节点的数据域的地址 不改变current if (current >link != NULL) return ¤t >link >data; else return NULL; Type *Next()//移动current到下一个节点 返回节点数据域的地址 if (current != NULL && current >link != NULL) prior = current; current = current >link; return ¤t >data; else return NULL; void Insert(const Type &value)//在当前节点的后面插入节点 不改变current Node<Type> *p = new Node<Type>(value current >link); current >link = p; BOOL InsertBefore(const Type &value)//在当前节点的前面插入一节点 不改变current 改变prior Node<Type> *p = new Node<Type>(value); if (prior != NULL) p >link = current; prior >link = p; prior = p; return TURE; else return FALSE;
BOOL Locate(int i)//移动current到第i个节点 if (i <= ) return FALSE; current = first >link; for (int j = ; current != NULL && j < i; j++ current = current >link) prior = current; if (current != NULL) return TURE; else return FALSE;
void First()//移动current到表头 current = first; prior = NULL; void End()//移动current到表尾 if (last >link != NULL) for ( ;current >link != NULL; current = current >link) prior = current; last = current; current = last;
BOOL Find(const Type &value)//移动current到数据等于value的节点 if (IsEmpty()) return FALSE; for (current = first >link prior = first; current != NULL && current >data != value; current = current >link) prior = current; if (current != NULL) return TURE; else return FALSE; BOOL Remove()//删除当前节点 current指向下一个节点 如果current在表尾 执行后current = NULL if (current != NULL && prior != NULL) Node<Type> *p = current; prior >link = p >link; current = p >link; delete p; return TURE; else return FALSE;
BOOL RemoveAfter()//删除当前节点的下一个节点 不改变current if (current >link != NULL && current != NULL) Node<Type> *p = current >link; current >link = p >link; delete p; return TURE; else return FALSE;
friend ostream & operator << (ostream & strm List<Type> &l) l First(); while (l current >link != NULL) strm << *l Next() << ; strm << endl; l First(); return strm;
protected:
/*主要是为了高效的入队算法所添加的 因为Insert() Remove() RemoveAfter()有可能改变last但没有改变last所以这个算法如果在public里除非不使用这些 否则不正确 但是last除了在队列中非常有用外 其他的时候很少用到 没有必要为了这个用途而降低Insert() Remove()的效率所以把这部分放到protected 实际上主要是为了给队列继承*/ void LastInsert(const Type &value)
Node<Type> *p = new Node<Type>(value last >link); last >link = p; last = p;
void Initialize()//当表为空表时使指针复位 current = last = first; prior = NULL;
//这部分函数返回类型为Node<Type>指针 是扩展List功能的接口 Node<Type> *pGet() return current; Node<Type> *pNext() prior = current; current = current >link; return current;
Node<Type> *pGetNext() return current >link;
Node<Type> *pGetFirst() return first;
Node<Type> *pGetLast() return last;
Node<Type> *pGetPrior() return prior;
void PutLast(Node<Type> *p) last = p; //这部分插入删除函数不建立或删除节点 是原位操作的接口
void Insert(Node<Type> *p) p >link = current >link; current >link = p; void InsertBefore(Node<Type> *p) p >link = current; prior >link = p; prior = p;
相关参考
数据结构学习讲座(C++)单链表(2) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!单链表()&n
数据结构学习讲座(C++)双向链表 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!双向链表 
销毁单链表 单链表被构造使用完后由于其结点均为动态分配的内存空间所以必须要销毁以释放空间否则会造成申请的内存不能释放单链表的销毁操作是创建操作的逆运算由于要修改单链表的头指针的指针变量所以要将头
图双向链表中的结点删除 双向链表的结束条件和单链表相同双向循环链表的结束条件和单向循环链表的结束条件相同 静态链表 根据上节单链表的知识用单链表表示线性表时其结点空间是在运行时根据需要动态分
单链表基本运算的实现 创建空单链表 链表与顺序表不同它是一种动态管理的存储结构链表中的每个结点占用的存储空间不是预先分配而是运行时系统根据需求生成的因此建立空单链表就是建立一个带头结点的空表该
求表长 由于单链表采用离散的存储方式并且没有显示表长的存储信息因此要求出单链表的表长必须将单链表遍历一遍 算法思路设一个移动指针p和计数器count初始化后p指向头结点p后移一个结点count
循环链表 对于单链表而言最后一个结点的指针域是空指针如果将该链表头指针置入该指针域则使得链表头尾结点相连就构成了循环单链表(也称单循环链表)如图所示 > 图带头结点的单循环链表 对循环单链
单链表的运算 建立单链表 假设线性表中结点的数据类型是字符我们逐个输入这些字符型的结点并以换行符\\n为输入条件结束标志符动态地建立单链表 的常用方法有如下两种 ()头插法建表 ①算法思
一单链表目录单链表反转找出单链表的倒数第个元素找出单链表的中间元素删除无头单链表的一个节点两个不交叉的有序链表的合并有个二级单链表其中每个元素都含有一个指向一个单链表的指针写程序把这个二级链表称一级单
双向链表结点的定义如下 typedefstructnode DataTypedata; structnode*prior*next; DuNode*DLinkList; 和单链表类似双向