一:表
1.1顺序表
实现-动态分配
#include<stdlib.h>
#define InitSize 10
typedef struct(){
int *data;
int MaxSize;
int length;
}SeqList
int main(){
SeqList(L);
InitList(L);
IncreaseList(L,5);
return 0;
}
void InitList(SeqList &L){
L.data = (int *)malloc(InitSize*sizeof(int))
L.length=0;
L.maxSize=InitSIze;
}
void IncreaseSize(SeqList &L,int len){
int *p = L.data;
L.data=(int *)malloc((L.MaxSize+len)*sizeof(int));
for(i=0; i<L.lenght; i++){
L.data[i]=p[i];
}
L.MaxSize=L.MaxSize+len;
free(p)
}
增加
#include<stlibs>
#define MaxSize 10
typedef sturct{
int data[MaxSize];
int length;
}SqeList;
int mian()}{
SqeList L;
InitList(L);
InsertList(L, 3, 3);
return 0;
}
bool InsertList(SqeList &L, int n, int e){
if(i<1||i>L.length+1)
return false;
if(L.length>=MaxSize)
return false;
for(int j=L.length;j>=i;j--)
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return ture;
}
删除
int mian(){
SeqList L;
InitList(L);
int e =-1;
if(DeleteList(L,3,e))
print("success=%d\n",e)
else
print("fail\n")
return 0;
}
bool DeleteList(SqeList &L,int i,int &e){
if(i<1||i>L.length)
retrun false;
e=L.data[i-1];
for(int j=i;j<L.length;j++){
L.data[j-1]=L.data[j];
}
L.length--;
return true;
}
按位查找
//静态分配
#define MaxSize 10
typedef struct{
int data[MaxSize];
int length;
}
//动态分配
#define InitSize 10
typedef struct{
ElemType *data;
int MaxSize;
int lenght;
}
ElemType GETElem(SeqList &L, int i){
return L.date[i-1];
}
按值查找
typedef struct{
int
}
1.2单链表
定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
#没有头节点的单链表
typedef struct LNode{
Elemtype data;
struct LNode *next;
}LNode, *LinkList;
bool InitList(LinkList &L){
L = NULL;
return true;
}
void test(){
LinkList L;
InitList(L);
}
bool Empty(LinkList L){
if(L==NULL)
return true;
else
return false;
}
bool Empty(LinkList L){
return (L==NULL)
}
#有头节点的单链表
#1.1
typedef struct LNode{
ElemType data;
struct LNode *next
}LNode, *LinkList;
#1.2
bool InitList(LinkList &L){
L = (LNode *) malloc(sizeof(LNode));
if (L==null)
return false;
L->next = NULL;
return ture;
}
#0
#
void test(){
LinkList L;
InitList(L);
}
#2 判断空表
bool Empty(LinkList L){
return (L->next==NULL)
}
插入(按位插入)
bool
#现在要在位序为i的地方插入数据e(带头节点)
#找到位置i-1,在后面插入数据
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
return false;
LNode *p;
********************************
#循环找到第i-1个节点
int j=0;
p = L;
while(!p=NULL && j<i-1){
p = p->next;
j++;
}
********************************
if(p==NULL)
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data = e;
s->next=p->next;
p->next=s;
return true;
}
#不带头节点
#插入第一个节点的操作与其他节点不同
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
retrun false;
if(i == 1){
LNode *s = (LNode *)malloc(sizeof(LNode));
}
#j=1代表是
int j=1;
}
#指定结点的后插操作
bool InsertNextNode(LNode *p, ElemType e){
if (p == NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
if (s==NULL)
return false;
s->date = e;
s->next = p->next;
p->next = s;
return true;
}
bool InsertPriorNode(LNode *p,ElemType e){
if(p==NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->next = p->next;
p->next = s;
s->data=p->data;
p->date = e;
return true;
}
bool InserPriorNode(LNode *p, LNode *s){
if(p==NULL || s == NULL)
return false;
s->next = p->next;
p->next = s;
ElemType temp = s->data;
s->data = p->data;
p->data = temp;
return true;
}
bool ListDelte(LinkList &L, int i, ElemType &e){
int j = 0;
LNode * p;
p =L;
if(p!=NULL && j<i-1){
p =p->next;
j++;
}
if (p==NULL)
return false;
if(p->next == NULL)
return false;
LNode * q = p->next;
p->next =q->next;
e = q->data;
free(q);
return true;
}
新建
#尾插法
#头插法
二:栈LIFO(只在一端进出)
联想记忆:坑
2.1基本操作
初始化(两种实现1.top=-1 2.top=0)
- top=0,栈满为top==MaxSize
- top=-1,栈满为top==MaxSize-1(下面代码top=-1)
```cpp
define MaxSize 10
typedef struct{ Elemtype data[Maxsize]; int top; }SeStack; void InitStack(SqStack &S){ S.top=-1; } void testStack(){ SqStack S; InitStack(S); }
bool StackEmpty(SqStack S){ if S.top==-1 return true; else return false; }
入栈
```cpp
#把指针+1,再把e数据进栈
#栈满要报错
bool Push(SqStack &S, Elemtype e){
#top0为第一个数
if(S.top==MaxSize-1)
return false;
S.data[++S.top]=e;
return true;
}
出栈
#栈顶数据出栈(用e返回),再把指针-1;
#栈空要报错
bool POP(SqStack &s, Elemtype &e){
if(S.top==-1)
return false;
e = S.data[S.top];
top--;
return true;
}
读栈顶
bool ReadTop(SqStack &S, ElemType &e){
if(S.top==-1)
return false;
e = S.data[S.top];
return true;
}
链栈(按照上面链的定义自己敲一遍基础操作的代码)
三:队列FIFO(一端进另一端出)
3.1顺序存储
联想记忆:排队
定义
#因为rear指向下一个应该插入的位置,故初始化的时候rear=front=0
#define MaxSize 10
typedef struct {
ElemType data[maxsize];
int front, rear;
}SqQueue;
void InitQueue(SqQueue &Q){
Q.rear=Q.front=0;
}
void testQueue(){
SeQueue Q;
InitQueue(Q);
}
bool QueueEmpty(SqQueue Q){
if(Q.rear=Q.front)
return true;
else
return false;
}
入队
#往队尾添加数据,并让rear+1,考虑到前面可能有空位置,故应让(rear+1)%MaxSize从而变为循环队列
#队列已满则错误
bool QueuePush(SqQueue &q, int i, Elemtype e){
if((Q.rear+1)%MaxSize==Q.front)
return false;
Q.data[Q.rear]=e;
Q.rear=(Q.rear+1)%MaxSize;
return ture;
}
判断队列满
1.一般
2.设置一个size记录队列长度
3.设置一个tag记录上一次的动作是删除还是添加
出队
#把队头的数据用x返回,并把front+1,考虑到循环性,让(front+1)%MaxSize
#队列空则出错
bool QueuePop(SqQueue &Q,Elemtype &e){
if(Q.rear==Q.front)
return false;
e=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;
return ture;
}
3.2链式存储
初始化
#带头节点:申请一个头结点,并让front(头节点)和rear都指向它;接着让头节点next为NULL
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct {
LinkNode *front,*rear;
}LinkQueue;
void InitQueue(LinkQueue &Q){
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
void testLinkQueue(){
LinkQueue Q;
InitQueue(Q);
}
#判断为空:Q.front==Q.rear || front->next=NULL
bool IsEmpty(LinkQueue &Q){
if(Q.front==Q.rear)
return true;
else
return false;
}
#不带头节点:front和rear全部指向NULL
void InitQueue(LinkQueue &Q){
Q.front=NULL;
Q.rear=NULL;
}
#判断为空:front=NULL || rear=NULL
bool IsEmpty(LinkQueue &Q){
if(Q.front==NULL)
return true;
else
return false;
}
入出
#申请一个节点,把节点赋值后让它next为空(因为一定是添加到队尾的);把队尾指针next给s,
# 并移动队尾指针到s上
bool LinkQueuePush(LinkQueue &Q,Elemtype e){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s.data = e;
s->next=NULL;
Q.rear->next=s;
Q.rear=s;
}
bool LinkQueuePop
四:串
4.1基本操作实现
4.1.1求子串
#遍历pos到pos+len-1,依次赋值给Sub串,记得让Sun长度变为len
#记得判断字串范围是否越界
SubString(&Sub, S, pos, len)
bool SubString(SString &Sub, SString S, int pos, int len){
if(pos+len-1>S.length)
return false;
for(int i = pos; i<pos+len;i++)
Sub.ch[i-pos+1]=S.ch[i];
Sub.length = len;
return true;
}
4.1.2比较大小
#同时遍历两个串,比较第一个不相同字符的大小。
#若扫描过的所有字符都相同,则长度长的串更大
StrCompare(S,T)
int StrCompare(SString S, SString T){
for(int i=1;i<=S.length&&i<=T.length;i++){
if(S.ch[i]!=T.ch[i])
return S.ch[i]-T.ch[i];
}
return S.length-T.length;
}
4.1.3定位操作
#对主串从头到尾依次取出长度为3的字串,再比较子串
int Index(SString S, SString T){
int i=1, n=StrLength(S), m= StrLength(T);
SString Sub;
while(i<=n-m+1){
SubString(sub, S, i, m)
if(StrCompare(Sub,T)!=0) ++i;
else return i;
}
return 0;
}
4.2朴素模式匹配算法:(不用基本操作完成字符匹配)
#用i,j逐个比较两串,并定义k作为主串匹配开始的标志符.ruo匹配失败,则继续下一个
int Index(SString S, SString T){
int k=1,i=1,j=1;
while(i<=S.Length&&i<=T.Length){
if(S.ch[i]==T.ch[j]){
i++;
j++;
}else{
k++;
i=k;
j=1;
}
}
if(j>T.length)
return k;
else
return 0;
}
#课本代码没有另外定义一个k,而是用i,j之间的逻辑关系来表示(指针后退重新开始匹配)
4.3KMP算法**
#和朴素匹配基本一样,只是不匹配时,不回溯i,只回溯j
int KMP(SString S, String T){
int i=1,j=1;
int next[T.length+1]; #看上图
get_next(T, next);
while(i<=S.Length&&i<=T.Length){
if(j==0||S.ch[i]==T.ch[i]){ #j=0是特殊情况
i++;
j++;
}else{
j=next[j];
}
}
if(j>T.length)
return i-T.length;
else
return 0;
}
4.3.1KMP算法的优化-nextval数组
g与l不匹配,next[4]=1,继续看g与l匹配,重复了
j=0时,i++;j++;所以l被跳过,匹配g与g