单链表:
  一.单链表与顺序表相比:

   1.顺序表可以方便的随机存取表中的任一节点,速度快;但是在表中插入删除一个数据时,为了保持其他元素的相对次序不变,平均需要移动一半的元素,效率很低;还有若事先对表长估计不足,过小会形成内存浪费,过大则需要拷贝到一个更大的数组,时间开销很大。相反,链表则适用于插入删除频繁,表长估计不定的情形。

   2.顺序表逻辑位置和物理位置都连续,而单链表中的逻辑位置连续,物理位置非连续。

   二.为什么要带附加表头?

    因为不带附加表头在插入删除时要分两种情况:操作节点在表头和不在表头;而带了附加表头便可以对所有节点一视同仁。

 template<class T>
struct LinkNode{//链表节点
T data;
LinkNode *link;
LinkNode(const T& args,LinkNode<T> *ptr=NULL){
data=args;
link=ptr;
}
}; template<class T>
class List{//带附加头节点的单链表
protected:
LinkNode<T> *first;//链表头指针
public:
List(){
first=new LinkNode<T>;
}
List(const T& x){
first=new LinkNode<T>(x);
}
List(List<T>& L){
T value;
LinkNode<T> *L_head=L.getHead();
LinkNode<T> *temp=first=new LinkNode<T>;
while(L_head->link!=NULL){
value=L_head->link->data;
temp->link=new LinkNode<T>(value);
L_head=L_head->link;
temp=temp->link;
}
temp->link=NULL;
}
~List(){
makeEmpty();
}
void makeEmpty(){//将链表置空
LinkNode<T> *temp;
while(first->link!=NULL){
temp=first->link;
first->link=temp->link;
delete temp;
}
}
int length()const{
LinkNode<T> *temp=first->link;
int count=;
while(temp!=NULL){
temp=temp->link;
count++;
}
return count;
}
LinkNode<T> *getHead()const{//返回附加头节点地址
return first;
}
LinkNode<T> *search(T x,int& i){//搜索数据x的地址和序列号
LinkNode<T> *current=first->link;
int index=;
while(current!=NULL){
if(current->data==x)
break;
current=current->link;
index++;
}
i=index;
return current;
}
LinkNode<T> *locate(int i){//搜索第i个节点的地址
if(i<)
return NULL;
LinkNode<T> *current=first;
int temp=;
while(current!=NULL&&temp<i){
current=current->link;
temp++;
}
return current;
}
bool getData(int i,T& x){//取出第i个元素的值
if(i<=)
return false;
LinkNode<T> *current=locate(i);
if(current==NULL) return false;
x=current->data;
return true;
}
void setData(int i,T& x){//修改第i个元素的值
if(i<=)
return;
LinkNode<T> *current=locate(i);
if(current==NULL) return;
current->data=x;
}
bool insert(int i,T& x){//在第i个元素后插入x
LinkNode<T> *current=locate(i);
if(current==NULL) return false;
LinkNode<T> *newNode=new LinkNode<T>(x);
newNode->link=current->link;
current->link=newNode;
return true;
}
bool remove(int i,T& x){//删除第i个元素的值
LinkNode<T> *current=locate(i-);
if(current==NULL||current->link==NULL) return false;
LinkNode<T> *del=current->link;
current->link=del->link;
x=del->data;
delete del;
return true;
}
bool isEmpty()const{
return (first->link==NULL)?true:false;
}
void inputFront(){//向前插入链表法
makeEmpty();
LinkNode<T> *newNode;
T value;
cin>>value;
while(value!=-){
newNode=new LinkNode<T>(value);
newNode->link=first->link;
first->link=newNode;
cin>>value;
}
}
void inputRear(){//向后插入链表法
makeEmpty();
LinkNode<T> *newNode,*last=first;
T value;
cin>>value;
while(value!=-){
newNode=new LinkNode<T>(value);
last->link=newNode;
last=newNode;
cin>>value;
}
}
void output(){//输出整个链表
LinkNode<T> *current=first->link;
while(current!=NULL){
cout<<current->data<<" ";
current=current->link;
}
cout<<endl;
}
};

测试代码如下:

 void menu(){
cout<<"1.向前插入建表(-1结束)"<<endl;
cout<<"2.向后插入建表(-1结束)"<<endl;
cout<<"3.输出链表"<<endl;
cout<<"4.搜索元素x所在节点的序号"<<endl;
cout<<"5.取出第i个元素的值"<<endl;
cout<<"6.用x的值修改第i个元素的值"<<endl;
cout<<"7.删除第i个元素"<<endl;
cout<<"8.在第i个元素后面插入x"<<endl;
cout<<"9.退出"<<endl;
} template<class T>
void function(int num,List<T> *list){
switch(num){
int x,i;
case :
list->inputFront();
break;
case :
list->inputRear();
break;
case :
list->output();
break;
case :
cin>>x;
list->search(x,i);
cout<<i<<endl;
break;
case :
cin>>i;
list->getData(i,x);
cout<<x<<endl;
break;
case :
cin>>x>>i;
list->setData(i,x);
break;
case :
cin>>i;
list->remove(i,x);
break;
case :
cin>>i>>x;
list->insert(i,x);
break;
default:
exit();
}
}
int main(int argc, char** argv) {
int num;
List<int> *list=new List<int>(-);
while(true){
menu();
cin>>num;
function(num,list);
}
return ;
}

其次是循环链表:

  代码我就不放了,就讲讲要修改的地方:

  1.构造函数。first=new LinkNode<T>;后面接上:first->link=first;目的是让自身首尾相连。如图:

  

   2.在判断循环指针是否到达表尾的条件要从NULL换成first。

   小结:

   循环链表的目的是只要知道表中任一一个节点的地址,就能遍历表中其他任一节点。

最后是双向链表:

  修改:

  1.节点的构造函数。需要增加一个前驱指针。

  2.搜索、插入删除算法。首先是方向,确定方向后算法和单链表差不多,区别在于通过前驱指针还是后续指针访问节点。其次是插入删除,讲起来比较啰嗦,直接看图:

  这是插入(中间是插入元素),虚线是原来的情况,实线是插入后的情况,可见一共涉及到4个指针。

  这是删除(中间是删除元素)。看上去也是涉及4个指针,实际只动了1和4。

  小结:

  双向链表的目的是为了解决在链表中不同方向(前/后)访问元素的问题。

  

单链表,循环链表,双向链表(C++实现)的更多相关文章

  1. 【 C# 】(一) ------------- 泛型带头节点的单链表,双向链表实现

    在编程领域,数据结构与算法向来都是提升编程能力的重点.而一般常见的数据结构是链表,栈,队列,树等.事实上C#也已经封装好了这些数据结构,在头文件 System.Collections.Generic ...

  2. js数据结构之链表(单链表、双向链表、循环链表)

    首先,链表有以下特点: 1. 存储空间不固定,可灵活扩充 2.方便多次的插入和删除,效率较高 单链表 单链表是最常用的链表,其对数据的操作均为单项的,向后查找的. /* 链表(基于对象) 此处为单链表 ...

  3. 数据结构与算法——链表 Linked List(单链表、双向链表、单向环形链表-Josephu 问题)

    链表是有序的列表,但是在内存中存储图下图所示 链表是以 节点 的方式来存储,是 链式存储 每个节点包含 data 域.next 域,指向下一个节点 链表的各个节点 不一定是连续存储,如上图所示 链表还 ...

  4. 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  5. 动态单链表的传统存储方式和10种常见操作-C语言实现

    顺序线性表的优点:方便存取(随机的),特点是物理位置和逻辑为主都是连续的(相邻).但是也有不足,比如:前面的插入和删除算法,需要移动大量元素,浪费时间,那么链式线性表 (简称链表) 就能解决这个问题. ...

  6. 线性表概述及单链表的Java实现

    一.线性表概述 线性表是指一组数据元素之间具有线性关系的元素序列,它表现为:除第一个元素没有直接前驱元素.最后一个元素没有直接后继元素外,其余所有元素都有且仅有一个直接前驱元素和直接后继元素. 根据存 ...

  7. js数据结构与算法--单链表的实现与应用思考

    链表是动态的数据结构,它的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 现实中,有一些链表的例子. 第一个就是寻宝的游戏.你有一条线索,这条线索是指向寻找下一条线 ...

  8. 数据结构学习--单链表(python)

    概念 链表(linked_list)是物理存储单元上非连续的.非顺序的存储结构,数据元素的逻辑顺序 是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间) ,另一个是指向 ...

  9. 使用OC实现单链表:创建、删除、插入、查询、遍历、反转、合并、判断相交、求成环入口

    一.概念 链表和数组都是一种线性结构,数组有序存储的,链表是无序存储的. 数组中的每一个元素地址是递增或者递减的关系,链表的每一个节点的地址没有此规律,它们是通过指针的指向连接起来. 链表种类:单链表 ...

随机推荐

  1. Dockerfile与Docker构建流程解读

    摘要 本文主要讨论了对docker build的源码流程进行了梳理和解读,并分享了在制作Dockerfile过程中的一些实践经验,包括如何调试.优化和build中的一些要点.另外,还针对现有Docke ...

  2. 墙上时钟时间 ,用户cpu时间 ,系统cpu时间

    一. 墙上时钟时间 ,用户cpu时间 ,系统cpu时间定义与联系 时钟时间(墙上时钟时间wall clock time):从进程从开始运行到结束,时钟走过的时间,这其中包含了进程在阻塞和等待状态的时间 ...

  3. jvm回收方法区

    很多人认为方法区(或者HotSpot虚拟机中的永久代)是没有垃圾收集的,Java虚拟机规范中确实说过可以不要求虚拟机在方法区实现垃圾收集,而且在方法区进行垃圾收集的“性价比”一般比较低:在堆中,尤其是 ...

  4. HTTP could not register URL http://+:86/. 设置VS默认以管理员权限打开

      在使用visual studio 2013启动self host webapi时候碰到下面的错误: 详细错误信息如下: HTTP could not register URL http://+:8 ...

  5. 关于Ueditor 前后端分离实现文件上传到独立服务器的问题 望大神们赐教

    最近,由于网站实现多台服务器负载均衡,导致编辑器上传文件需要同步,可是使用同步软件太慢,不太现实,所以想到实现编辑器上传文件直接上传到独立文件服务器.可是没想到遇到坑了. 1.在本地IIS 中添加网站 ...

  6. app外包开发注意事项大全『最新』

    随着移动互联网的高速发展,很多互联网创业公司或传统向互联网转型的公司都急需发开一款app软件,多数公司会选择让外包公司来开发.问题来了,App外包市场鱼龙混杂,我们要如何在这里面选择一个靠谱的公司,这 ...

  7. 【C#】Switch datatype between object and byte[]

    This sample shows how to turn object to byte[], as well as turn byte[] to object. So,I can turn any ...

  8. sublime3下载安装及常用插件

    之前与学习前端有关的软件都安装在了实验室电脑上,最近由于要放寒假(也许我寒假回去会学习呢),于是得在笔记本电脑上重新安装一遍.几个软件各种出错,花了一下午才安装好,必须记录下来啊! 这篇文章主要介绍s ...

  9. eclipse集成配置JDK和Tomcat

    在eclipse中集成JDK和tomcat服务器方法很简单,我们可以在服务器上运行想要的东西.比如我们学习javaweb时就要用到. 工具/原料   eclipse,JDK,tomcat 方法/步骤 ...

  10. nginx 配置访问限制

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Helvetica Neue"; color: #454545 } p. ...