单链表之C++实现
在实现单链表时要注意对单链表的逻辑存储、物理存储有清晰的概念。
如上图链表已经完成,其逻辑结构如上。当需要对其进行操作,比如插入、删除,通常需要引
入指针,如上的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++实现的更多相关文章
- 时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法
有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和 ...
- 单链表的C++实现(采用模板类)
采用模板类实现的好处是,不用拘泥于特定的数据类型.就像活字印刷术,制定好模板,就可以批量印刷,比手抄要强多少倍! 此处不具体介绍泛型编程,还是着重叙述链表的定义和相关操作. 链表结构定义 定义单链表 ...
- Java实现单链表的各种操作
Java实现单链表的各种操作 主要内容:1.单链表的基本操作 2.删除重复数据 3.找到倒数第k个元素 4.实现链表的反转 5.从尾到头输出链表 6.找到中间节点 7.检测链表是否有环 8.在 ...
- [LeetCode] Linked List Cycle II 单链表中的环之二
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...
- c++单链表基本功能
head_LinkNode.h /*单链表类的头文件*/#include<assert.h>#include"compare.h"typedef int status; ...
- 单链表、循环链表的JS实现
数据结构系列前言: 数据结构作为程序员的基本知识,需要我们每个人牢牢掌握.近期我也展开了对数据结构的二次学习,来弥补当年挖的坑...... 当时上课的时候也就是跟着听课,没有亲自实现任何一种数据结 ...
- C代码实现非循环单链表
C代码实现非循环单链表, 直接上代码. # include <stdio.h> # include <stdlib.h> # include <malloc.h> ...
- 分离的思想结合单链表实现级联组件:CascadeView
本文介绍自己最近做省市级联的类似的级联功能的实现思路,为了尽可能地做到职责分离跟表现与行为分离,这个功能拆分成了2个组件并用到了单链表来实现关键的级联逻辑,下一段有演示效果的gif图.虽然这是个很常见 ...
- 数据结构:单链表结构字符串(python版)添加了三个新功能
#!/urs/bin/env python # -*- coding:utf-8 -*- #异常类 class stringTypeError(TypeError): pass #节点类 class ...
- 数据结构:单链表结构字符串(python版)改进
此篇文章的replace实现了字符串类的多次匹配,但依然有些不足. 因为python字符串对象为不变对象,所以replace方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...
随机推荐
- MyEclipse第一个Servlet程序 --解决Win7系统下MyEclipse与Tomcat连接问题
前言 本文旨在帮助学习java web开发的人员,熟悉环境,在Win7系统下运行自己的第一个Servlet程序,因为有时候配置不当或系统原因可能会运行不成功,这给初学者带来了一定烦恼,我也是为此烦恼过 ...
- JAVA泛型编程笔记
1介绍 Java泛型编程是JDK1.5版本后引入的.泛型让编程人员能够使用类型抽象,通常用于集合里面. 下面是一个不用泛型例子: List myIntList=new LinkedList(); // ...
- [Cycle.js] Main function and effects functions
We need to give structure to our application with logic and effects. This lessons shows how we can o ...
- Android播放音频的两种方式
一种使用MediaPlayer,使用这种方式通常是播放比较长的音频,如游戏中的背景音乐. 代码如下: private MediaPlayer mPlayer = null; mPlayer = Med ...
- tomcat配置数据源
1.修改conf下的context.xml,在<context>标签中添加: <Resource name="jdbc/soa" auth="Conta ...
- 掌握jQuery插件开发,这篇文章就够了
---恢复内容开始--- 在实际开发工作中,总会碰到像滚动,分页,日历等展示效果的业务需求,对于接触过jQuery以及数据jQuery使用的人来说,首先想到的肯定是寻找现有的jQuery插件来满足形影 ...
- WebApi2官网学习记录---批量处理HTTP Message
原文:Batching Handler for ASP.NET Web API 自定义实现HttpMessageHandler public class BatchHandler : HttpMess ...
- Windows服务简单实例
1.定时器使用 partial class TimerService : ServiceBase { public TimerService() { InitializeComponent(); } ...
- jQuery选择器的学习
jQuery的核心在于它的选择器,通过观看视频和阅读,发现jQuery选择器大体上的分类可分为这么几种(不同人方式不同,这里选择一个自认为比较好的): 1.基础选择器(对应api文档中的基本选择器和层 ...
- python之简单入门01
python简单的介绍使用: 一.个人感觉写Python程序,最好用的工具就是pycharm了,自动补全功能可以满足大多数不太喜欢记忆的人群: 安装pycharm之前应该先安装python解释器,目 ...