单链表之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方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...
随机推荐
- c指针点滴1
#include <stdio.h> #include <stdlib.h> void main() { ; int *p = #//&num是一个地址 ...
- awk实践积累
#cat iii |awk '{max=$2;min=$2;for (i=2;i<=NF;i++) if ($i>max) max=$i fi} {for (i=2;i<=NF;i+ ...
- python下载多个文件
# -*- coding: utf-8 -*-__author__ = 'Administrator'import urllib2,urllib,os,redef Url1(url):#多个文件 ...
- c/c++ 复习基础要点01-const指针、指针函数 函数指针、new/delete与malloc/free区别与联系
1. 引用本身是有指针实现的:引用为只读指针 例子: int d=123; int& e=d; //引用 int * const e=d; //只读指针,e指向d,不可修改e指 ...
- 快速构建AdapterView的Adapter--ingeniousadapter
项目地址:ingeniousadapter 前面的话:本项目的原型是QuickAdapter,它们的思路基本一致,但本项目的优势在于: 支持AdapterView存在多个layout类型 可配置图片加 ...
- nagios和zabbix自定义监控脚本
一. 自定义nagios监控脚本1. 在客户端上创建脚本/usr/local/nagios/libexec/check_disk.shvim /usr/local/nagios/libexec/ch ...
- keepalived vip漂移基本原理及选举算法
keepalived可以将多个无状态的单点通过虚拟IP(以下称为VIP)漂移的方式搭建成一个高可用服务,常用组合比如 keepalived+nginx,lvs,haproxy和memcached等.它 ...
- 从反编译的角度去观察C#6.0
1. 自动属性初始化 (Initializers for auto-properties) 1.1 C#6.0 之前的写法 public class FirstExperience { private ...
- Java ----------- SQL语句总结(更新中。。。。。。)
#对数据库的操作 *创建数据库 CREATE DATABASE database_name:database_name为创建的数据库的变量名称. #对表的操作
- 转载 Silverlight实用窍门系列:1.Silverlight读取外部XML加载配置---(使用WebClient读取XAP包同目录下的XML文件))
转载:程兴亮文章,地址;http://www.cnblogs.com/chengxingliang/archive/2011/02/07/1949579.html 使用WebClient读取XAP包同 ...