单链表之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方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...
随机推荐
- Codeforces Round #311 (Div. 2) E - Ann and Half-Palindrome(字典树+dp)
E. Ann and Half-Palindrome time limit per test 1.5 seconds memory limit per test 512 megabytes input ...
- HDU 2074 叠筐
叠筐 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission ...
- KVO详解
NSKeyValueObserving非正式协议定义了一种机制,它允许对象去监听其它对象的某个属性的修改. 我们可以监听一个对象的属性,包括简单属性,一对一的关系,和一对多的关系.一对多关系的监听者会 ...
- Controller返回值类型ActionResult
在mvc中所有的controller类都必须使用"Controller"后缀来命名 并且对Action也有一定的要求: 必须是一个public方法 必须是实例方法 没有标志NonA ...
- SVN CornerStone的使用
http://www.henishuo.com/mac-cornerstone-svn-use/
- cocos2dx 碰撞检测
//必须 要有float类型的参数 void MainScene::updateFrame(float dt) { if (spriteTest != NULL && spriteTe ...
- 二维码生成 - QrCodeNet
下载QrCodeNet /// <summary> /// 生成QR码 /// </summary> /// <param name="output_path& ...
- js中的两个数字a,b求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。一共b个数字相加,例如用户输入2,5 s=2+22+222+2222+22222
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- java运算
(一) 截图: 程序: import javax.swing.JOptionPane; public class Addition { public static void main (String ...
- 线段树练习 codevs 1080
/* codevs 1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 一行N个方格,开 ...