单链表,循环链表,双向链表(C++实现)
单链表:
一.单链表与顺序表相比:
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++实现)的更多相关文章
- 【 C# 】(一) ------------- 泛型带头节点的单链表,双向链表实现
在编程领域,数据结构与算法向来都是提升编程能力的重点.而一般常见的数据结构是链表,栈,队列,树等.事实上C#也已经封装好了这些数据结构,在头文件 System.Collections.Generic ...
- js数据结构之链表(单链表、双向链表、循环链表)
首先,链表有以下特点: 1. 存储空间不固定,可灵活扩充 2.方便多次的插入和删除,效率较高 单链表 单链表是最常用的链表,其对数据的操作均为单项的,向后查找的. /* 链表(基于对象) 此处为单链表 ...
- 数据结构与算法——链表 Linked List(单链表、双向链表、单向环形链表-Josephu 问题)
链表是有序的列表,但是在内存中存储图下图所示 链表是以 节点 的方式来存储,是 链式存储 每个节点包含 data 域.next 域,指向下一个节点 链表的各个节点 不一定是连续存储,如上图所示 链表还 ...
- 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 动态单链表的传统存储方式和10种常见操作-C语言实现
顺序线性表的优点:方便存取(随机的),特点是物理位置和逻辑为主都是连续的(相邻).但是也有不足,比如:前面的插入和删除算法,需要移动大量元素,浪费时间,那么链式线性表 (简称链表) 就能解决这个问题. ...
- 线性表概述及单链表的Java实现
一.线性表概述 线性表是指一组数据元素之间具有线性关系的元素序列,它表现为:除第一个元素没有直接前驱元素.最后一个元素没有直接后继元素外,其余所有元素都有且仅有一个直接前驱元素和直接后继元素. 根据存 ...
- js数据结构与算法--单链表的实现与应用思考
链表是动态的数据结构,它的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 现实中,有一些链表的例子. 第一个就是寻宝的游戏.你有一条线索,这条线索是指向寻找下一条线 ...
- 数据结构学习--单链表(python)
概念 链表(linked_list)是物理存储单元上非连续的.非顺序的存储结构,数据元素的逻辑顺序 是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间) ,另一个是指向 ...
- 使用OC实现单链表:创建、删除、插入、查询、遍历、反转、合并、判断相交、求成环入口
一.概念 链表和数组都是一种线性结构,数组有序存储的,链表是无序存储的. 数组中的每一个元素地址是递增或者递减的关系,链表的每一个节点的地址没有此规律,它们是通过指针的指向连接起来. 链表种类:单链表 ...
随机推荐
- Android替换APP字体 — Typeface
Android替换APP字体 — Typeface APP字体的思路一般都会想到自定义控件(TextView.EditView),但是项目中会有很多种控件,就算用也会承担一些风险和资源的消耗,主要是这 ...
- FTP之虚拟用户
基于虚拟用户访问ftp关闭防火墙,selinux 过程如下1.装包,配置.起服务配置过程如下: 需写入vsftpd.conf配置文件中的内容如下: anonymous_enable=NO ---- 匿 ...
- 结构-行为-样式-JqueryUI拖放使用实例(全)
最近工作中有个需要是动态配置页面,想到之前公司有做过类似的,用的是JqueryUi,所以就看了下它的Api.下面就是我做的小Demo,想用的同学可以参考: Html: <div class=&q ...
- hdu1041
#include <iostream> #include <string> using namespace std; const int SIZE = 1001; const ...
- Jquery datepicker 时间插件使用 js 时间相加,相减
$(document).ready(function(){ //输入框事件 $('#probation').bind('input propertychange', function() { var ...
- js分页模板
/** *参数说明: *currentPage:当前页数 *countPage:总页数 *changeMethod:执行java后台代码的js函数,即是改变分页数据的js函数 */ function ...
- PRML 第二章mindmap
PRML第二章的Mindmap,这一章读的比较快,主要是很多计算和证明的过程都跳过了,感觉不是特别需要认真去看每一个公式,能够记住每个小节的结论.公式就可以了.当然有能力.有时间的人还是可以认真读的, ...
- arm指令集
http://blog.chinaunix.net/uid-20769502-id-112445.html
- <video>和<audio>标签,对视频和音频的支持
H5新增了<video>和<audio>标签,提供对视频和音频的支持 <audio>的属性与<video>属性相同 <video> vide ...
- 关于VS2010编译警告LNK4221
最近研究duilib,准备把里面自定义的一些工具类如CDuiString什么的用ATL的替换掉,于是遇到久仰大名的 warning C4251: xxx needs to have dll-int ...