在实现单链表时要注意对单链表的逻辑存储、物理存储有清晰的概念。

如上图链表已经完成,其逻辑结构如上。当需要对其进行操作,比如插入、删除,通常需要引

入指针,如上的ptr1、ptr2。在编程时一定要注意通过ptr1、ptr2对链表结构的操作是正确的。

而不仅仅是你觉得正确的。

下面给大家看下我的单链表的实现,错误之处还请指正。

1、VC6实现,包括三个文件:sll.h、sll.c、main.c

2、sll.h单链表类、结点类的说明

#ifndef _SLL_H_
#define _SLL_H_ //加以下两句是为了使链表中包含的数据类型可以更灵活
#define dataType int
#define endOfData 0 //单链表的节点
class node
{
public:
dataType data;
node *next;
}; //单链表,其中保存的元素为整数
class sll
{
public:
sll(); //构造函数
~sll(); //析构函数
void create(); //建立一个链表
int getLength(); //获取链表长度
void reverse(); //链表倒置
bool insert(int pos,dataType num); //插入某一位置的某一值.插入成功返回true;否则返回false.位置从0开始向上累加
void del(dataType num); //删除某一所有值
node* getHead(); //获取链表头
void print(); //打印所有元素
int find(dataType num); //在链表中寻找num.若找到返回首次找到的下标,若找不到则返回-1
dataType getNum(int pos); //根据pos找到对应结点的data域的值,若找不到则返回endOfData private:
node *head; //链表头指针
}; #endif

3、sll.c单链表类成员函数的实现

#include <iostream>
#include "sll.h"
using namespace std; sll::sll() //构造函数
{
head = NULL;
} sll::~sll() //析构函数
{
node *ptrNode = head;
node *ptrNodeTmp = NULL; while(ptrNode != NULL)
{
ptrNodeTmp = ptrNode->next;
delete ptrNode;
ptrNode = ptrNodeTmp;
}
} void sll::create()
{
node *ptrNode = new node;
ptrNode->data = endOfData;
head = ptrNode; //保存头结点指针 bool flag = true; //flag=true继续建单链表,flag=false链表建立完成
bool flagNumOne = true; //flagNumOne表示是链表的第一个元素
dataType data = endOfData; //dataType和endOfData在sll.h中定义 while(flag)
{
cout<<"输入节点数据: "; //一个一个的输入结点
cin>>data; if(data != endOfData)
{ //没有输入建链表结束标志endOfData,则继续建链表
if(!flagNumOne)
{
node *tmpPtr = new node; ptrNode->next = tmpPtr;
ptrNode = tmpPtr;
} ptrNode->data = data; flagNumOne = false;
}
else
{ //输入结束标志endOfData,则结束建链表
flag = false;
ptrNode->next = NULL;
}
} if(head->data == endOfData) //链表为空的情况
{
head = NULL;
delete ptrNode; //如果链表中没有元素,则要释放程序申请的唯一结点
}
} int sll::getLength()
{
int num = 0;
node *ptrNode = head; while(ptrNode != NULL)
{
num++; //未到链表结尾则继续累加
ptrNode = ptrNode->next; //链表延展
} return num;
} void sll::del(dataType num)
{
//ptrNodeMain和ptrNodeAssit在起始时是指向同一结点的,以后都是指向一前一后的两个点,ptrNodeAhead在前(更接近链表结束)
node *ptrNodeAhead = head;
node *ptrNodeFellow = ptrNodeAhead; while(ptrNodeAhead != NULL) //链表要从头找到尾,删除链表中所有等于num的结点
{
while(ptrNodeAhead->data != num && ptrNodeAhead->next != NULL) //未找到num结点,也未到链表结尾,指针向下扩展
{
ptrNodeFellow = ptrNodeAhead;
ptrNodeAhead = ptrNodeAhead->next;
} if(ptrNodeAhead->data == num) //找到num结点
{
if(ptrNodeAhead == head) //如果num节点是头结点
{
head = ptrNodeAhead->next;
delete ptrNodeAhead;
ptrNodeAhead = head;
ptrNodeFellow = ptrNodeAhead;
}
else //如果num节点不是头结点
{
ptrNodeFellow->next = ptrNodeAhead->next;
delete ptrNodeAhead;
ptrNodeAhead = ptrNodeFellow->next;
}
}
else //链表搜索结束也未找到num结点
{
ptrNodeAhead = NULL;
}
}
} bool sll::insert(int pos,dataType num)
{
if(pos < 0 || pos >= getLength()) //判断插入结点的正确位置是(0 ~ getLength()-1)
{
return false;
} node *ptrNodeAhead = head;
node *ptrNodeFollow = NULL;
int tmpNum = 0;
while(1) //获取插入位置的指针,ptrNodeAhead指向待插入的位置,ptrNodeFollow指向带插入位置的下一结点
{
if(tmpNum++ == pos)
{
break;
} ptrNodeFollow = ptrNodeAhead;
ptrNodeAhead = ptrNodeAhead->next;
} //以下两句将待插入结点的数据准备好
node *ptrTmpNode = new node;
ptrTmpNode->data = num; if(ptrNodeAhead == head) //如果是插入头结点
{
ptrTmpNode->next = head;
head = ptrTmpNode;
}
/*
else if(ptrNodeAhead->next == NULL)
{
ptrNodeAhead->next == ptrTmpNode;
ptrTmpNode->next = NULL;
}
*/
else //插入中间节点,此种方法永远也不能插入尾结点,插入是前向的
{
ptrNodeFollow->next = ptrTmpNode;
ptrTmpNode->next = ptrNodeAhead;
} return true;
} node* sll::getHead()
{
return head; //返回链表头结点指针
} void sll::reverse()
{
node *ptrNodeAhead = head;
node *ptrNodeFllow = NULL;
node *ptrTmp = NULL; while(ptrNodeAhead != NULL)
{
ptrTmp = ptrNodeAhead->next;
ptrNodeAhead->next = ptrNodeFllow;
ptrNodeFllow = ptrNodeAhead;
ptrNodeAhead = ptrTmp;
} head = ptrNodeFllow;
} void sll::print()
{
node *ptrNode = head; while(ptrNode != NULL)
{
cout<<ptrNode->data<<" "; ptrNode = ptrNode->next;
}
cout<<endl;
} int sll::find(dataType num)
{
node *ptrNode = head;
int index = 0; while(ptrNode != NULL)
{
if(ptrNode->data == num)
{
return index; //返回第一个num结点的下标
} ++index;
ptrNode = ptrNode->next; //链表向下延展
} return -1; //未找到num结点返回-1
} dataType sll::getNum(int pos)
{
if(pos < 0 || pos >= getLength()) //判断pos的正确位置是(0 ~ getLength()-1)
{
return endOfData;
} int index = 0;
node *ptrNode = head; while(1)
{
if(index++ == pos)
{
return ptrNode->data;
} ptrNode = ptrNode->next;
}
}

4、main.c

#include <iostream>
#include "sll.h"
using namespace std; int main()
{
sll exp; exp.create(); cout<<"The len of sll: "<<exp.getLength()<<endl;
exp.print(); exp.del(2);
exp.print(); exp.insert(2,999);
exp.print(); exp.reverse();
exp.print(); cout<<"2的位置在: "<<exp.find(2)<<endl; cout<<exp.getNum(3)<<endl; return 0;
}

5、测试结果

单链表之C++实现的更多相关文章

  1. 时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法

    有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和 ...

  2. 单链表的C++实现(采用模板类)

    采用模板类实现的好处是,不用拘泥于特定的数据类型.就像活字印刷术,制定好模板,就可以批量印刷,比手抄要强多少倍! 此处不具体介绍泛型编程,还是着重叙述链表的定义和相关操作.  链表结构定义 定义单链表 ...

  3. Java实现单链表的各种操作

    Java实现单链表的各种操作 主要内容:1.单链表的基本操作 2.删除重复数据 3.找到倒数第k个元素   4.实现链表的反转   5.从尾到头输出链表 6.找到中间节点 7.检测链表是否有环 8.在 ...

  4. [LeetCode] Linked List Cycle II 单链表中的环之二

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...

  5. c++单链表基本功能

    head_LinkNode.h /*单链表类的头文件*/#include<assert.h>#include"compare.h"typedef int status; ...

  6. 单链表、循环链表的JS实现

    数据结构系列前言: 数据结构作为程序员的基本知识,需要我们每个人牢牢掌握.近期我也展开了对数据结构的二次学习,来弥补当年挖的坑......   当时上课的时候也就是跟着听课,没有亲自实现任何一种数据结 ...

  7. C代码实现非循环单链表

    C代码实现非循环单链表, 直接上代码. # include <stdio.h> # include <stdlib.h> # include <malloc.h> ...

  8. 分离的思想结合单链表实现级联组件:CascadeView

    本文介绍自己最近做省市级联的类似的级联功能的实现思路,为了尽可能地做到职责分离跟表现与行为分离,这个功能拆分成了2个组件并用到了单链表来实现关键的级联逻辑,下一段有演示效果的gif图.虽然这是个很常见 ...

  9. 数据结构:单链表结构字符串(python版)添加了三个新功能

    #!/urs/bin/env python # -*- coding:utf-8 -*- #异常类 class stringTypeError(TypeError): pass #节点类 class ...

  10. 数据结构:单链表结构字符串(python版)改进

    此篇文章的replace实现了字符串类的多次匹配,但依然有些不足. 因为python字符串对象为不变对象,所以replace方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...

随机推荐

  1. c语言验证哥德巴赫猜想(从4开始 一个偶数由两个质数之和)

    #include <stdio.h> #include <stdlib.h> #include <math.h> int isit(int num) { int i ...

  2. c语言结构体1之定义

    这是在复习阶段随便小结的一些东西 别喷哦 结构体定义的三种方式 注意事项: 1结构体括号后面有分号 2#define得放在程序上面 3成员名可以和结构体名相同 4结构体类型不能直接访问成员,也不能赋值 ...

  3. QListWidget方式显示缩略图

    最近在工作中经常遇到了一个问题就是把把文件夹中的图片全部以缩略图的形式显示出来,刚开始的时候一头雾水,不知道怎么办,经过在网上查资料,发现QListWidget控件可以实现图片的缩略图显示,但是不知道 ...

  4. Java 高效 MVC & REST 开发框架 JessMA v3.2.1 即将发布

        JessMA(原名:Portal-Basic)是一套功能完备的高性能 Full-Stack Web 应用开发框架,内置可扩展的 MVC Web 基础架构和 DAO 数据库访问组件(内部已提供了 ...

  5. WebGIS在行业中应用的演变

    结合我本身的项目及WebGIS在公检法行业中的应用,对此作了一个演变过程的总结:         第一阶段:GIS基本功能的应用:Data Show(数据展示):Search(搜索):Search b ...

  6. hdu 5080 2014ACM/ICPC鞍山K题 polya计数

    首先,中心点是能够直接算出来的 把全部的坐标相加再除n就能够 然后枚举一个不靠近中心的点,枚举它绕中心点旋转的角度.仅仅要枚举50次就能够了 计算出当前枚举的的角度能否形成一个置换群 计算循环节,再用 ...

  7. linux提取指定行至指定位置

    grep查找ERROR,定位位置 awk打印到指定行数 sed打印到文本末尾 awk打印到文本末尾 方法一 #!/bin/csh -f if(-f errorlog.rpt) then rm -rf ...

  8. 解决System.Data.SQLite兼容32位和64位问题

    将当前说明文档的目录下的x64.x86目录和System.Data.SQLite.dll文件复制到您的应用程序根目录中(注意更新引用,引用System.Data.SQLite.dll即可,两目录中的不 ...

  9. TravelCMS旅游网站系统诞生记-1(后台框架篇)

  10. cobar和tddl分享

    Cobar是阿里巴巴(B2B)部门开发的一种关系型数据的分布式处理系统,它可以在分布式的环境下看上去像传统数据库一样为您提供海量数据服务.那么具体说说我们为什么要用它,或说cobar--能干什么?以下 ...