数据结构库的具体实现(C/C++)
数据结构
干锅土鸡
这个作者很懒,什么都没留下…
展开
-
算法的时间复杂度
问题:如何用符号定性的判断算法的效率? 不管是i *= 3;还是i *= 4;都是O(logn) i=0;->n i=1;->n-1 i=2;->n-2 … i=n-1;->1 那么相加后得到O[n(n+1)/2] ===> O(n²) O(n²) t(n)==>O(n) for(int i=0;i<n;i++) t(i); ==>O(n²) for(int i=0;i<n;i++) for(int j=i;j<n;j++) t.原创 2021-09-19 00:24:05 · 65 阅读 · 0 评论 -
算法效率的度量
空间换时间的例子: /* 问题: 在一个由自然数1-1000中某些数字所组成的数组中,每个数字可能出现零次或者多次。 设计一个算法,找出出现次数最多的数字。 */ #include <iostream> using namespace std; void search(int a[], int len) // O(n) { int sp[1000] = {0};//0-999格子记录出现的次数 int max = 0; ...原创 2021-09-19 11:53:55 · 71 阅读 · 0 评论 -
学习数据结构的意义
原创 2021-09-19 12:39:14 · 92 阅读 · 0 评论 -
智能指针分析
#ifndef SMARTPOINTER_H #define SMARTPOINTER_H namespace DragonLib { template <typename T> class SmartPointer { protected: T* m_pointer; public: SmartPointer(T* p=NULL) { m_pointer=p; } SmartPointer(const SmartPointer<原创 2021-09-20 01:29:05 · 81 阅读 · 0 评论 -
异常类的构建
子类可以赋值给父类(赋值兼容性) ArithmeticException:计算异常(1/0) NullPointerException:空指针异常(需要合法指针时得到的却是空指针) IndexOutOfBoundsException:越界异常(数组越界) NoEnoughMemoryException:内存不足异常(需要动态内存申请时没有空间了) InvalidParameterException:参数错误异常(算法需要接受参数,判定参数是否合法) Exception:顶层抽象父类,抽象接口,产生不了对.原创 2021-09-20 12:20:07 · 110 阅读 · 0 评论 -
一个库的顶层父类创建
记住:原创 2021-09-20 23:52:14 · 76 阅读 · 0 评论 -
类族结构的进化
单一继承树原则: 为什么这么重载new之后,SmartPointer<int>* sp = new SmartPointer<int>();这行代码执行的是重载的new?一是因为Object是所有类的基类 SmartPointer<int>* sp = new SmartPointer<int>(); //SmartPointer<int>* sp=static_cast<SmartPointer<int>*>(Ob原创 2021-09-21 01:00:35 · 76 阅读 · 0 评论 -
线性表的本质操作
线性表(List)的表现形式 零个或多个数据元素组成的集合 数据元素在位置上是有序排列的 数据元素的个数是有序排列的 数据元素的个数是有限的 数据元素的类型必须相同 虚函数,这个类用来被继承的!不可以用来定义对象,但是可以定义类指针不会报错的! 小结 ...原创 2021-09-21 11:09:06 · 67 阅读 · 0 评论 -
线性表的顺序存储结构
s原创 2021-09-21 21:03:33 · 107 阅读 · 0 评论 -
顺序存储结构的抽象实现
#ifndef SEQLIST_H #define SEQLIST_H #include "List.h" #include "Exception.h" namespace DragonLib { template <typename T> class SeqList : public List<T> { protected: T* m_array; int m_length; public: bool insert(int i,const T&am..原创 2021-09-22 22:50:27 · 70 阅读 · 0 评论 -
StaticList和DynamicList
构造函数中,将父类m_array指向子类创建的m_space,很巧妙 接下来进行测试: 更多的测试交由大家! 否,两个类对于顺序存储空间的指定截然不同,没有任何关系 小结原创 2021-09-24 00:24:56 · 89 阅读 · 0 评论 -
顺序存储线性表的分析
s2=s1; 这样操作之后,s2中数组中的int*类型的指针也指向元素,如果析构会造成两次释放空间,程序崩溃! 外部无法调用protected下的构造函数,无法拷贝构造和赋值操作 在List中实现尾插法: virtual bool insert(const T& e)=0; 在SeqList中实现: bool insert(const T& e) { return insert(m_length,e);//直接调用之前实现的头插法 } list...原创 2021-09-24 01:42:16 · 98 阅读 · 0 评论 -
数组类的创建(上):StaticArray
线性表可能被当成数组乱用! 数组类创建的意义,就是替代C++原生数组! #ifndef ARRAY_H #define ARRAY_H #include "Object.h" #include "Exception.h" namespace DragonLib { template <typename T> class Array : public Object { protected: T* m_array; public: virtual bool set(in原创 2021-09-24 15:25:51 · 185 阅读 · 0 评论 -
数组类的创建(下):DynamicArray
#ifndef DYNAMICARRAY_H #define DYNAMICARRAY_H #include "array.h" #include "Exception.h" namespace DragonLib { template <typename T> class DynamicArray : public Array<T> { protected: int m_length; public: DynamicArray(int length) ...原创 2021-09-24 18:13:12 · 248 阅读 · 0 评论 -
线性表的链式存储结构
回顾:为啥要数组类? 线性表会被误用成数组,当数组来使用,所以开发了数组类,代替C++原生数组! C++中struct与class唯一区别就是struct默认成员属性为 创建的链表是个泛型·,可以保存任意类型! next是直接后继的地址 ...原创 2021-09-26 11:45:55 · 58 阅读 · 0 评论 -
顺序表和单链表的对比分析
实际开发中,时常判断元素是否在链表中: 可以对它进行封装 在List.h中加入代码: virtual int find(const T& e) const=0; //SeqList.h: //LinkList.h 测试: 编译报错!因为对象之间不能比较:(没有重载==操作符) 重载一下: 两全的方法,在Object顶层父类中重载: 链表时间复杂度几乎都是:O(n) 工程中单链表用的很多,但是效率比较低,为啥用这么多呢? 小结 ...原创 2021-09-26 22:26:49 · 62 阅读 · 0 评论 -
单链表遍历与优化
LinkList增加成员变量: Node* m_current; int m_step; 这四个函数相互依赖、配合才能高效遍历 这么遍历就很高了:O(n),每次遍历只移动一次游标即可! 把LinkList.h代码中的new Node() 和 delete都替换成上述函数… 小结 ...原创 2021-09-26 23:50:38 · 170 阅读 · 0 评论 -
静态单链表的实现
代码优点难以消化,需要多看!这里重写create函数,有点巧妙…一时间消化不了… 小结原创 2021-09-27 19:54:26 · 95 阅读 · 0 评论 -
Bugfix
来看看strdup在Glibc 2.20(标准C库)中的实现: 默认参数s不为空指针,这个在我们的数据结构库中是有问题的 改进: 当前版本g++编译器不允许析构函数抛异常这么做 打印出来结果:1 3 然后程序崩溃 我们都删除了元素1,但是怎么还打印3?应该还有两个元素才对。 改进: 更改在m_length–;和destroy(toDel);两行交换位置,destroy后再长度减一,这样子不够安全,所以交换一下位置就可以了!这叫异常安全! 第一行是随机值 3对应的堆内存已经删除了,还去打印它.原创 2021-09-29 20:16:44 · 300 阅读 · 0 评论 -
再论智能指针(上)
替换成SmartPointer: 测试: 直接崩溃 比如: 智能指针军规之一:一片空间只能一个指针指着… 先把之前SmartPointer替换的地方再改回来… SmartPointer.h中直接删除一下函数代码,因为父类中已经实现了: 打印: 接下来就是测试SmartPointer的工作了,不演示… ...原创 2021-09-30 23:19:53 · 65 阅读 · 0 评论 -
再论智能指针(下)
测试: 小结原创 2021-10-01 01:08:16 · 74 阅读 · 0 评论 -
循环链表的实现
CircleList.h: 结果: 3 6 9 12 15 18 21 24 27 30 33 36 39 1 5 10 14 19 23 28 32 37 41 7 13 20 26 34 40 8 17 29 38 11 25 2 22 4 35 16 31 所以:站在16 31 不会死 小结原创 2021-10-02 02:19:16 · 58 阅读 · 0 评论 -
双链表的实现
倒序打印单链表的值,这样子效率很低: 双链表和单链表内部机制不一样,所以不能是继承关系,只能是兄弟关系。 插入操作: 1、2代表next指针,3、4代表pre指针 插入代码实现: 删除操作: ...原创 2021-11-25 18:15:12 · 254 阅读 · 0 评论 -
Linux中的两个宏(offsetof、container_of)
编译器是这么干的: 也就是说编译器没有真的去访问pst所指向地址中的内容,只是用pst地址加上偏移大小。 所以说offsetof这个Linux宏的意思是,计算出偏移长度: 功能:通过结构体中的一个变量,就知道结构体的初试地址值。 这一行的代码作用是做类型检查 将这一行代码去掉 改成container_of_new这一个新的宏来做实验: 运行的结果不是我们想要的! 使用原版的container_of来做实验,会发现报了一个警告!告诉我们存在一个类型不兼容的情况! 传入的c是ch...原创 2021-11-25 20:18:13 · 222 阅读 · 0 评论 -
Linux内核链表剖析
/* * This file is part of the DTLib template project, http://www.dt4sw.com * * The MIT License (MIT) * * Copyright (c) 唐佐林 (Delphi Tang) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and asso...原创 2021-12-05 01:42:49 · 319 阅读 · 0 评论 -
双向循环链表的实现
#ifndef DUALCIRCLELIST_H #define DUALCIRCLELIST_H #include "LinuxList.h" #include "DualLinkList.h" namespace DTLib { template < typename T > class DualCircleList : public DualLinkList<T> { protected: struct Node : public Object ...原创 2021-12-14 22:59:07 · 769 阅读 · 0 评论 -
栈的概念及实现
栈的唯一特性: //Stack.h #ifndef STACK_H #define STACK_H #include "Object.h" namespace DTLib { template < typename T > class Stack : public Object { public: virtual void push(const T& e) = 0; virtual void pop() = 0; virtual T top() con.原创 2021-12-15 00:59:09 · 389 阅读 · 0 评论 -
StaticQueue队列的概念及实现
抽象类无法生成对象 为何用循环计数法?高效!原创 2022-01-03 15:43:01 · 409 阅读 · 0 评论 -
LinkQueue链式队列的实现
#ifndef LINKQUEUE_H #define LINKQUEUE_H #include "Queue.h" #include "linklist.h" #include "Exception.h" namespace DragonLib { template <typename T,int N> class StaticQueue : public Queue { protected: LinkList<T> m_list; public: Link...原创 2022-01-03 18:45:30 · 597 阅读 · 0 评论 -
栈实现队列&队列实现栈
一个栈无法实现队列,那么两个栈就可以实现队列了!原创 2022-01-15 02:50:24 · 149 阅读 · 0 评论 -
字符串类的创建(上)
接下来为DragonLib创建字符串类: #include "dtstring.h" #include <cstring> #include <cstdlib> #include "Exception.h" using namespace std; namespace DragonLib { void String::init(const char* s) { m_str = strdup(s); if(m_str) { m..原创 2022-01-15 14:51:49 · 289 阅读 · 0 评论 -
字符串类的创建(下)
//非const就用&,因为可以出现在赋值号左边 char& String::operator[] (int i) { if((0<=i) && (i<m_length)) { return m_str[i]; } else { THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid...\n"); } }..原创 2022-01-15 16:37:16 · 347 阅读 · 0 评论 -
KMP子串查找算法
那么部分匹配表怎么获得? 实现关键 PMT[1]=0;(下标为0的元素匹配值为0) 从2个字符开始递推(从下标为1的字符开始递推) 假设PMT[n]=PMT[n-1]+1(最长共有元素的长度) 当假设不成立,PMT[n]在PMT[n-1]的基础上减小 部分匹配表是前辈找到的规律,不需要理解,会用就行! 获得部分匹配表函数如下: int* make_pmt(const char* p) { int len = strlen(p); int* ret = static_...原创 2022-01-15 21:47:37 · 407 阅读 · 0 评论