线性表是具有相同类型的N(N>=0)个元素的有限序列,其中n为表长,当N==0时为空表.。
一组地址连续存放的储存单元依次存放在线性表的元素,从而使得逻辑上的相邻两个元素物理位置也相邻
template<class T> class SqList
{
private:
T *Data;
int length=0;
int MaxSize=16;
public:
SqList(){
Data=new T[MaxSize];
}
~SqList(){
delete Data;
}
bool ListInsert(int index,T data){
if(index<0||index>length)return false;
if(length==MaxSize){
T *Data_T=new T[MaxSize*2];
for(int i=0;i<MaxSize;i++)Data_T[i]=Data[i];
delete Data;
Data=Data_T;
MaxSize*=2;
}
for(int i=length;i>index;i--)Data[i]=Data[i-1];
Data[index]=data;
length++;
return true;
}
bool ListDelete(int index){
for(int i=index;i+1<length;i++)Data[i]=Data[i+1];
length--;
}
int ListFindByKey(T x){
for(int i=0;i<length;i++)if(x==Data[i])return i;
return -1;
}
T ListFindByIndex(int index){
if(index<0||index>=length)return NULL;
return Data[index];
}
bool IsEmpty(){
return length==0;
}
int ListLength(){
return length;
}
};
线性表的链式储存称为单链表
template<class T> class LinkNode
{
public:
T data;
LinkNode* next;
LinkNode(T Data){
data=Data;
next=NULL;
}
};
template<class T> class LinkList
{
private:
LinkNode<T> *head;
public:
LinkList(){
head=new LinkNode<T>(NULL);
}
LinkNode<T>* LinkListByKey(T data){
LinkNode<T>*p=head;
while(p!=NULL&&p->data!=data)p=p->next;
return p;
}
LinkNode<T>* LinkFindByIndex(int Index){
LinkNode<T>*p=head;
for(int i=0;i<Index&&p!=NULL;i++)p=p->next;
return p;
}
void LinkInsert(LinkNode<T>* pre,T data){
LinkList* p=new LinkList(data);
p->next=pre->next;
pre->next=p;
}
void LinkDelete(LinkList* Elemte){
if(Elemte==NULL)return;
LinkNode<T>*p=head;
while(p->next!=Elemte)p=p->next;
if(p->next==Elemte){
p=Elemte->next;
delete Elemte;
}
}
bool IsEmpty(){
return head->next==NULL;}
int getLength(){
int length=0;
LinkNode<T>*p=head;
while(p->next!=NULL)length++,p=p->next;
return length;
}
};
只允许在一段插入或者删除的线性表
特点:后入先出
栈的基本操作
本质:受限制的顺序表
储存方式:顺序表、链表
template<class T> class Stack
{
private:
T *Data;
int length=0;
int MaxSize=16;
public:
Stack(){
Data=new T[MaxSize];
}
~Stack(){
delete Data;
}
void Push(T data){
if(length==MaxSize){
T* Data_T=new T[MaxSize*2];
for(int i=0;i<MaxSize;i++)Data_T[i]=Data_T[i];
delete Data;Data=Data_T;
MaxSize*=2;
}
Data[length++]=data;
}
void pop(){
if(length==0)return NULL;
length--;
}
T top(){
if(length==0)return NULL;
return Data[length-1];
}
bool IsEmpty(){
return length==0;
}
};
只允许在一段插入在另一段者删除的线性表
特点:先入先出
栈的基本操作
本质:受限制的顺序表
储存方式:顺序表、链表
template<class T> class Queue
{
private:
T *Data;
int L=0,R=0;
int MaxSize=16;
public:
Queue(){
Data=new T[MaxSize];
}
~Queue(){
delete Data;
}
void Push(T data){
if((R+1)%MaxSize==L){
T* Data_T=new T[MaxSize*2];
for(int i=0;i<MaxSize;i++)Data_T[i]=Data[(L+i)%MaxSize];
delete Data;
Data=Data_T;
L=0;R=MaxSize-1;
MaxSize*=2;
}
Data[(R+1)%MaxSize]=data;
R=(R+1)%MaxSize;
}
void pop(){
if(L<R)
L=(L+1)%MaxSize;
}
T top(){
return Data[(R+MaxSize-1)%MaxSize];
}
bool IsEmpty(){
return L==R;
}
};
串是由零个或者多个有限字符组成的序列
子串串中任意连续个字符组成的序列
暴力匹配 时间复杂的O(mn)
struct SString{
int length;
char *ch;
};
int SString_match(SString S,SString T){
for(int i=0;i+T.length<S.length;i++){
int flag=0;
for(int j=0;j<T.length;j++)
if(S.ch[i+j]!=T.ch[j]){
flag=1;break;
}
if(flag==0)return i;
}
return -1;
}
一种进行快速字符串匹配的算法 时间复杂度O(m+n)
需要一个next数组辅助计算.
next[y]内储存一个位置x ,x是最大的可以满足满足子串[0,x]是子串[0,y]的后缀的位置
求next数组过程,可以通过一个线性递推求出
匹配的时候利用next数值 直接跳到可以可能匹配的最大位置,不需要回溯重新匹配。
struct SString{
int length;
char *ch;
};
int GetNext(SString S,int Next[]){
Next[0]=-1;
int K=0;
for(int i=1;i<S.length;i++){
while(K!=-1&&S.ch[K]!=S.ch[i])K=Next[K];
Next[i]=K++;
}
}
int KMP_match(SString S,SString T,int Next[]){
for(int i=0,j=-1;i<S.length;i++){
while(j!=-1&&S.ch[i]!=T.ch[j+1])j=Next[j];
if(S.ch[i]==T.ch[j+1])j++;
if(j+1==T.length)return i-T.length+1;
}
return -1;
}
树是n(n>=0)个结点的有限集合,n=0时称为空树
对于任意非空树满足
树中一个结点的子结点的个数称为该结点的度
树中最大的度称为 树的度
度大于0的结点是 分支结点
度等于0的结点是 叶子结点
二叉树n(n>=0)个结点的有限集合
二叉树和度为2的树的区别
** 特殊二叉树**
二叉树的储存
struct BiTree{
TElemType data;
BiTree*lchild,*rchild;
BiTree(TElemType Data){
data=Data;
lchild=rchild=NULL;
}
};
先序遍历
void PreOrder(BiTree* root){
if(root!=NULL){
visit(root);
PreOrder(root->lchild);
PreOrder(root->rchild);
}
}
中序遍历
void InOrder(BiTree* root)
{
if(root!=NULL)
{
InOrder(root->lchild);
visit(root);
InOrder(root->rchild);
}
}
后序遍历
void PostOrder(BiTree* root)
{
if(root!=NULL)
{
PostOrder(root->lchild);
PostOrder(root->rchild);
visit(root);
}
}
层序遍历
void LevelOrder(BiTree* root)
{
Queue<BiTree* >q;
q.Push(root);
while(q.IsEmpty()==false){
BiTree* rt=q.top();
q.pop();
visit(rt);
if(rt->lchild!=NULL)q.Push(rt->lchild);
if(rt->rchild!=NULL)q.Push(rt->rchild);
}
}
一种简单的集合表示
类似于树,只有一个指针指向根结点。
并差集的基本操作
#define MaxSize 100;
int fa[MaxSize];
void init(){
for(int i=0;i<MaxSize;i++)fa[i]=i;
}
int find(int x){
return fa[x]==x?x:find(fa[x]);
}
void join(int x,int y){
x=find(x);y=find(y);
fa[y]=x;
}
对于并差的查找可以做一下优化,每次查找到树的根节点后,将经过的结点全部指向根节点,减小树链的深度。
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
并差集常常用于判断二个结点是否属于同一棵树,或者判断是否有环。
给二叉树加上线索,使得二叉树线性化。
void InThread(ThreadNode* root,ThreadNode* &pre){
if(root!=NULL){
InThread(root->lchild,pre);
if(root->lchild==NULL){
root->ltag=1;
root->lchild=pre;
if(pre!=NULL){
pre->rchild=root;
pre->ltag=1;
}
}
pre=root;
InThread(root->rchild,pre);
}
}
二叉排序树 BST 又称作 二叉查找树。
二叉排序树的性质
二叉排序树的基本操作
#define TElemType int
struct BiTree{
TElemType data;
BiTree*lchild,*rchild;
BiTree(TElemType Data){
data=Data;
lchild=rchild=NULL;
}
};
void BiTree_init(BiTree * root){
root=NULL;
}
void BiTree_destory(BiTree* root){
if(root->lchild!=NULL)BiTree_destory(root->lchild);
if(root->rchild!=NULL)BiTree_destory(root->rchild);
delete root;
}
void BiTree_insert(BiTree *&root,TElemType data){
if(root==NULL)root=new BiTree(data);
if(root->data!=data){
if(data < root->data)BiTree_init(root->lchild);
else BiTree_init(root->rchild);
}
}
BiTree* BiTree_sreach(BiTree * root,TElemType data){
if(root==NULL)return NULL;
if(root->data==data)return root;
if(data<root->data)return BiTree_sreach(root->lchild,data);
return BiTree_sreach(root->rchild,data);
}
void BiTree_delete(BiTree *&root,TElemType data){
if(root!=NULL){
if(root->data==data){
if(root->lchild!=NULL&&root->lchild!=NULL){
BiTree *p=root->lchild;
while(p->rchild!=NULL)p=p->rchild;
TElemType tmp_Data=p->data;
BiTree_delete(root,tmp_Data);
root->data=tmp_Data;
}else{
if(root->lchild==NULL&&root->rchild==NULL){
delete root;
root=NULL;
}else
if(root->lchild!=NULL){
BiTree *p=root->lchild;
delete root;
root=p;
}else{
BiTree *p=root->rchild;
delete root;
root=p;
}
}
}else{
if(data<root->data)BiTree_delete(root->lchild,data);
else BiTree_delete(root->rchild,data);
}
}
}
二叉平衡树的性质
给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。