点滴数据结构(c++)

一、c++与线性表

入门篇

基本概念:

  • 数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。
  • 数据元素:是由数据组成的、有一定意义的基本单位,有时也称为record.
  • 数据对象:有相同性质的数据元素的集合,是数据的子集。
  • 数据:可以输入到计算机,能被程序处理的符号,包括整数型,实型以及字符型等。

数据结构的分类:
从逻辑上而言:表示数据元素之间的关系。

  • 集合结构
  • 线性结构
  • 树形结构
  • 图形结构

从存储的物理结构,也就是数据在计算机中的存储形式:

  • 顺序存储
  • 链式存储

c++动态存储分配:new与delete

int *p = new int ;  // 会自动进行进行类型转换,得到int类型的指针
Point *p = new Point[100] ; //得到一个数组指针
delete []p ; //释放该数组
delete p ; // 仅仅释放指针p所指向的第一个,而失去其他位置的空间,而无法复用他们

c++ friend 友元

类的封装过程中包含了private函数以及public函数。为了使另外的类能够访问本类的private函数,可以通过友元对其“赋予权限”。

class List;  //类的前视说明

class LinkNode{
friend class List;
private:
	int data;
}

class List{
public:
	//链表公共类
private:
	//链表私有类}

友元的关系不具有对称性。这里,LinkNode类中生命了List是它的友元,哪里List的所有成员都可以直接使用LinkNode的私有成员,反之,LinkNode则不能。

顺序表与数组之间的差别

  • 顺序表: 各个表项的逻辑循序与其存放的物理顺序一致,第i个元素存放在data[]的第i-1个位置。各个表元素必须相继存放在一个连续的空间内
  • 数组:只有两个按元素的下标存或者取,这样,以为数组中的数据可能是跳跃式的、不连续存放的。
    顺序表的应用:两个顺序表的‘与’运算和‘并’预算的实现。
    顺序表的优缺点评价,优点:
    节点间逻辑简单,无需额外的空间存储逻辑关系,存储利用率高;课方便的存取任一节点,存取速度快;
    缺点:插入或删除元素时效率低,平均需要移动一半的元素;需要连续的空间。

单链表

单链表的存储结构

typedef struct Node{
	ElemType data; //可以是整形数据或者结构体的数据类型
	struct Node *next ;
};

单链表的插入与删除
插入:在表的第一个节点;插入在首尾节点;插入在尾节点。
删除:删除第一个节点;删除中间或尾部。
整表创建
举例:前插入法

    for (int i = 0; i < count; i++)
    {
        Node *p = new Node ;
        p->data = i ;
        p->next = head->next ;
        head->next = p ;
    }

整表删除

Status ClearList(LinkList *L){
	LinkList *p,*q;
	p = L ;
	while(p){
		q = p->next;
		delete(p) ;
		p = q ;
	}
	return ok ;
}

静态链表

链表需要进行指针操作,那么能不能将这种指针的方式来进行通用化,使一些没有指针的编程语言也能利用这种操作呢。这里可以利用数组。
让数组的元素由两个数据域组成,data与cur。数据域用来表示data,cur来表示next指针,存放该元素的下一个数组在数组中的位置,称cur为游标。用数组来描述的链表叫做静态链表

双向链表

循环链表

栈的链式存储结构

// 代表栈内的一个元素
typedef struct StackNode{
	ElemType data ; //ElemType代表了数据类型
	struct StackNode *next ;
}StackNode, *LinkStackPtr;

typedef struct LinkStack{
	LinkStack top; //指向栈顶指针
	int count;	
}

//example
// 在栈中插入元素
bool Push(LinkStack *S, ElemType e){
	// 新建一个栈单元
	LinkStackPtr ss;
	ss->data = e ;
	ss->next = S->top;
	S->top = ss;
	S->count ++ ; //记录栈内元素的数量
	return true ;
}

//同理,有出栈操作为(将栈顶值返回为e并删除栈顶)
bool Pop(LinkStack *S, ElemType *e){
	// 新建一个栈单元,使其获取栈顶
	LinkStackPtr p;
	if(StackEmpty(*S))
		return error;
	e = S->top->data ;
	p = S->top;
	S->top = S->top->next ;
	free(p) ;
	s->count -- ;
	return true ;
}

队列(循环队列)

队列中,如果数据要进行频繁的出队入队操作,链式结构可能需要频繁的进行内存分配等操作,带来很大的开销。
循环队列就很适合这样的问题,它的主要特点在于:定义了队列的maxsize,以及由两个指针来指示队列中数据。
下面给出构造循环队列的类的代码。

class SqQueue{
//在public中存放构造函数、析构函数以及其他的队列操作函数
public:
	SqQueue(int size);  //size为打算存放的数据量
	virtual ~SqQueue();
	bool EnQueue(int data);
	bool DeQueue(int* pRecvData=nullptr);
	void DeTraverse(); //遍历队列中存储的数据元素
	int GetSize();//获取队列中的数据量
	bool IsFull();
	bool IsEmpty();
private:
	ElemType data[size] ;
	int front ; //头指针
	int rear ; //尾指针
	int length ; //队列的实际长度
};

链队列

队列的链式存储结构,其实就是线性表的单链表,只不过它能尾进头出罢了。
下面给出链队列的结构。这个需要定义两个东西,其一是队列中每一个element结构的定义,按照链式队列,中间的每一个元素都包含了数据部分以及指针部分。其二则是队列结构的定义,队列是有许多个element组成的,有许多的成员函数,以及有头指针和尾指针。队列元素可用用class定义或者struct结构体进行定义,这里,我均采用class来定义

template <class T >
class QNode{
	T data; //
	QNode *next ;
};

template <class T>
class LinkQueue{
public:
	//定义成员函数
	void InitQueue(Linkqueue *Q); //队列的初始化
	...
private:
	QNode *front; //尾指针
	QNode *rear; //尾指针
};

//队列的初始化
void Linkqueue::InitQueue(Linkqueue *Q) {
    QNode *p = new QNode;
    p->next = NULL;
    Q.front = p;
    Q.rear = p;
}

串中,需要掌握KMP模式匹配算法。
这个算法可以参考知乎上的一些教程。
其实就是一个匹配前缀和后缀最大相等的长度。前缀:除去最后一个字符,后缀:除去第一个字符。

树的存储结构
双亲表示法

孩子表示法
孩子兄弟表示法

参考文献:

  • 《大话数据结构》程杰
  • 《数据结构》 殷人昆
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值