从顺序表到串的线性表知识体系【数据结构】


线性表主要由顺序表示或链式表示。在实际应用中,常以栈、队列、字符串等特殊形式使用

定义

线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。

存储结构

顺序表(顺序表示)

1.定义顺序表

typedef struct Sqlist{
   Elemtype *elem;
   int length;
   int listsize;
}Sqlist; //定义顺序表 

2.初始化顺序表

Status InitSqlist(Sqlist &L){
     //初始化顺序表 
    L.elem=(Elemtype *)malloc(List_init_size*sizeof(Elemtype));
    if(!L.elem)exit(OVERFLOW);//exit  退出系统 
    L.length=0;//清空顺序表长度 
    L.listsize=List_init_size;//初始存储容量 
    return OK;
}

3.插入操作

Status SqlistInsert(Sqlist &L){
       //插入运算 
    printf("请输入插入数据的位置\n");
    int i; 
    scanf("%d",&i);
    while(i<1||i>L.length+1){
    	if(i<1||i>L.length+1==0)break;
        int i2;
		printf("error:插入位置错误\n请重新输入插入的位置:\n");	 
	    scanf("%d",&i2);
	    i=i2;
	}
    if(L.length>=L.listsize)
    {
      Elemtype *newbase;
      newbase=(Elemtype *)realloc(L.elem,LISTNCREMENT*sizeof(Elemtype));
      if(!newbase)return ERROR;
      L.elem=newbase;
      L.listsize+=LISTNCREMENT;
    }
       printf("请输入该学生数据\n");
   Elemtype e;
   scanf("%s%s%d",e.no,e.name,&e.score);
    Elemtype *p,*q;
    q=&(L.elem[i-1]);//指向插入位置i 
    for(p=&(L.elem[L.length-1]);p>=q;--p)
    *(p+1)=*p;//从最后一个元素开始往后移,移至第i个位置 
    *q=e;
    ++L.length;
    return OK;
}

4.删除操作


Status DeleteSqlist(Sqlist &L){
      //删除运算 
       printf("请输入要删除数据的位置\n");
   int i; 
   scanf("%d",&i);
   Elemtype e; 
   while(i<1||i>L.length){
    	if(i<1||i>L.length==0)break;
        int i2;
		printf("error:删除位置错误\n请重新输入删除的位置:\n");	 
	    scanf("%d",&i2);
	    i=i2;
	}  
   e=L.elem[i-1];
   Elemtype *p,*q;
   q=&L.elem[i];
   for(p=q;p<=&L.elem[L.length-1];p++){*(p-1)=*p;}
   L.length--;
   return OK;
}

5.查找操作

Status SearchSqlist(Sqlist &L){
	//查找运算 
   char g[12];
   printf("请输入要查询的学生的学号\n");
   scanf("%s",g);
   int i=0,j;
  for(j=0;j<=L.length-1;j++){
  	if(strcmp(g,L.elem[j].no)==0)printf("该学生信息为:\n%s\t%s\t%d\n",L.elem[j].no,L.elem[j].name,L.elem[j].score);
  	else 	 i++;
  }	
  if(i==L.length){
  printf("error:该学生不存在\n请重新输入要查询的学生:\n");
  SearchSqlist(L);
  }
  return OK;
}

链表(链式表示)

单链表

1.定义结点类型

typedef struct LNode{
	//定义结点类型
	ElemType data;//数据域 
	struct LNode* next;//指针域 (递归定义数据类型)
}LNode;

2.定义链表

typedef LNode* LinkList; //定义链表类型,节点类型的指针类型就是链表 

3.初始化链表

Status InitLNode(LinkList &L){
	//初始化空链表 
	L=new LNode;//相等于L=(LNode *)malloc(sizeof(LNode));
	L->next=NULL;
	if(!L)return 0;
	return OK;
}

4.插入操作

Status InsertLinkList(LinkList &L,int i,ElemType e){
	//向第i个位置之前插入一个结点
	int length=GetLength(L); 
	if(i<1||i>length+1)exit(ERROR);	
	LinkList p,q;
	p=L;//p指向头节点 
	int j=1;
	while(p && j<i){//p指向第i个元素前驱的时候停止 
		p=p->next;
		++j;
	}
	//InitLNode(q);
	q=new LNode;
	q->data=e;
	q->next=p->next;//新插入的元素的指针指向原来第i个元素 
	p->next=q;//第i-1个元素的指针指向新插入的元素 
    printf("插入成功!\n");
    return OK;
	 

5.删除操作

Status Delete(LinkList &L,int i,ElemType &e){
	//删除第i个元素 
	int length=GetLength(L); 
	if(i<1||i>length)exit(ERROR);	
	LinkList p,q;
	p=L;
	int j=1;
	while(p && j<i){//p指向第i个元素前驱的时候停止 
		p=p->next;
		++j;
	}
	q=p->next;
    e=q->data;//保存要删除的元素 
    p->next=q->next;//第i-1个元素指向第i+1个元素 
    printf("删除成功!\n");
    return OK;
}

6.查找操作

Status GetElem(LinkList L,int i,ElemType &e){
	//读取第i个元素的值
	int length=GetLength(L); 
	if(i<1||i>length)exit(ERROR);	
	LinkList p;
	p=L->next;
	int j=1;
	while(p && j<i){//p指向第i个元素前驱的时候停止 
		p=p->next;
		++j;
	}
    e=p->data;
    return OK;
}

7.创建含有n个结点的链表 (头插法)

Status CreatList_T(LinkList &L,int n){//创建含有n个结点的单链表 (头插法)    
	for(int i=0;i<n;i++){
		LinkList p; 
		p=new LNode;//创建一个新的结点类型,p指向该空间,p就是该结点 
		printf("请输入数据\n");
		scanf("%d",&p->data);
		p->next=L->next;//新节点的后驱为上一个节点 
		L->next=p;//记录新结点的位置 
	}
}

8.创建含有n个结点的单链表 (尾插法)

Status CreatList_W(LinkList &L,int n){//创建含有n个结点的单链表 (尾插法)
    LinkList r;
    r=L;//尾指针指向头结点 
    for(int i=0;i<n;i++){
		LinkList p; 
		p=new LNode;//创建一个新的结点类型,p指向该空间,p就是该结点 
		printf("请输入数据\n");
		scanf("%d",&p->data);
		p->next=NULL;//新结点的指针指向为空 
		r->next=p; //尾结点指向新的结点 
		r=p;//记录新结点的位置,新节点就成为尾结点 
	}
} 

实际应用

栈、

栈

顺序栈
1.定义顺序栈

 typedef struct SqStack{
        ElemType *base;    //栈底指针
        ElemType *top;     //栈顶指针
        int stacksize;     //栈可用的最大容量
    }SqStack;
  1. 初始化顺序栈
Status InitStack(SqStack &S)
    {
        S.base=new ElemType[NUM]//为顺序栈分配一个最大容量为NUM的数组空间
        if(!S.base)return 0;    //存储分配失败
        S.top=S.base;           //top初始为base  ,空栈
        S.stacksize=NUM;         //stacksize设置为栈的最大容量NUM
        return 1;
     }
  1. 顺序栈的入栈
 Status Push(SqStack &S,ElemType e){
       if(S.top-S.size==S.stacksize){//栈满
       S.base=(ElemType*)realloc(S.base,sizeof(ElemType)*S.stackszie*2)
       if(!S.base)return 0;
       S.top=S.base;
       S.stacksize*=2;
       }
     *S.top=e;
     S.top++;
     return 1;
    } 
  1. 顺序栈的出栈
 Status Pop(Sqstack &S,ElemType &e){
        if(S.top==S.base)return 0;//栈空
        S.top--;     //因为top指针一般指向下一个空间
        e=*S.top;
        return 1}

5 取顺序栈的栈顶元素

  Staus    GetTop(SqStack &S){
       //返回S的栈顶元素,不修改栈顶指针
       if(S.top!=S.base)return *(S.top-1);//栈非空时执行
    }
  1. 求顺序栈的长度 S.top-S.base;
  2. 清空顺序栈 S.top=S.base;
  3. 销毁顺序栈
 Status DestroyStack(SqStack &S){
    if(S.base){
       free(S.base);
       S.stacksize=0;
       S.base=S.top=NULL;
    }
    return 1;
    }   

链栈
1.定义链栈的结点和链表

typedef struct StackNode{
       ElemType data;
       struct StackNode *next;
    }StackNode;
    typedef StackNode* LinkStack;//定义链栈链表
  1. 链栈的初始化
 void InitStack(LinkStack &S)
    {
        S=NULL;
    }

3.判断链栈是否为空

Status StackEmpty(LinkStack &S)
    {
      if(!S)return 0;
      return 1;
    } 
  1. 链栈进栈
 Status Push(LinkStack &S,ElemType e)
    {
        p=(LinkStack)malloc(sizeof(StackNode))
        if(!p)return 0;
        p->data=e;
        p->next=S;
        S=p;
        return 1;
    }
  1. 链栈出栈
  Status Pop(LinkStack &S,ElemType e)
    {
       if(!S)return 0;//栈空
       e=S->data;
       LinkStack p;
       p=S;
       S=S->next;
       delete p;//p=S指向栈顶,delete p,删除该栈顶空间 
       return 1;
    }
  1. 取栈顶元素
   Status GetTop(StackList &S){
       if(!S)return 0;//栈空
       return S->data;
    }          

队列、

队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素。
队列

循环队列-------队列的顺序表示
1.定义顺序队列

  typedef struct
        {
           QElemType *base;//存储空间的首地址
           int front;//头指针
            int rear;//尾指针
        }SqQueue;
  1. 初始化顺序队列
  Status InitQueue(SqQueue &Q)
       {
           Q.base=new QElemType[MAXSIZE];//为队列分配一个最大容量为MAXSIZE的数组空间
           if(!Q.base)exit(OVERFLOW);//分配空间失败
           Q.front=Q.rear=0;//头指针和尾指针置为零,队列为空
           return OK;
       }

3.求队列长度

 int QueueLength(SqQueue Q)
       {
          return(Q.rear-Q,front+MAXQSIZE)%MAXQSIZE; //少用一个存储空间
       }
  1. 入队
   Status EnQueue(SqQueue &Q,QElemType e)
       {
            if((Q.rear+1)%MAXQSIZE==Q.front)//少用一个存储空间,表明队满
            return ERROR;
            Q.base[Q.rear]=e;  //新元素插入队尾
            Q,rear=(Q.rear+1)%MAXSIZE;//队尾指针加1
            return OK;
       }
  1. 出队
  Status DeQueue(SqQueue &Q,QElemType &e)
      {
         if(Q.front==Q.rear)return ERROR;//队空
         e=Q.base[Q.front];//保存队头元素
         Q.front=(Q.front+1)%MAXSIZE//队头指针加1
         return OK; 
       }

6.取循环队列的队头元素

SElemType GetHead(SqQueue Q)
{//返回Q的队头元素,不修改队头指针
    if(Q.front!=Q.rear)//队列非空
         return Q.base[Q.front];//返回队头元素的值,队头指针不变
}

链队–队列的链式表现
1. 定义结点类型,结点指针类型

 typedef struct QNode{
        QElemType data;
        struct QNode *next;
      }QNode,*QueuePtr;

2.定义链队

  typedef struct{
            QueuePtr front;
            QueuePtr rear;
         }LinkQueue;

3.初始化链队

Status InitQueue(LinkQueue &Q)
{
    Q.front=Q.rear=new QNode;//生成新结点作为头结点,队头和队尾指针都指向此结点
    Q.front->next=NULL;//头指针的指针域置空
    return OK;
}

4.入队

    Status EnQueue(LinkQueue &Q,QElemType e)
	{
	      p=new QNode;//为入队元素分配结点空间
	      if(!p)exit(OVERFLOW);
	      p->data=e;
	      p->next=NULL;
	      Q.rear->next=p;//将新结点插入到队尾
	      Q.rear=p;//修改队尾指针
	      return OK;
	   }

5.出队

   Status DeQueue(LinkQueue &Q,QELemType &e)
   {
        if(Q.front==Q.rear)reurn ERROR;//队列为空
        p=Q.front->next;//p指向队头元素
        e=p->data;//保存队头元素的值
        Q.front->next=p->next;//修改头指针
        if(Q.rear==p)Q.rear=Q.front;//最后一个元素被删,队尾指针指向头结点
        delete p;//释放空间
        return OK;
    } 

6.取队头元素
与循环队列一样,当队列非空时,此操作返回当前队头元素的值,队头指针保持不变

	SElemType GetHead(LinkQueue Q)
	{
		 if(Q.front!=Q.rear)//队列非空
		      return Q.front->next->data;//返回队头元素的值        
	}

7.销毁链队列

  Status DestroyQueue(LinkQueue &Q)
     {
            while(Q.front){
               Q.rear=Q.front->next;
               free(Q.front);
               Q.front=Q.rear;
            }
            return OK;
        }
  1. 判断链队是否为空
 Status QueueEmpty(LinkQueue Q)
  {
              return(Q.front==Q.rear);
  }

字符串、

一、存储结构
1.串的顺序存储:用一组地址连续的存储单元存储串值得序列。
typedef unsigned char SString[Maxsize];
SString S;
2.串的堆顺序存储结构:
typedef struct{
char *ch;//若是非空串,按串长分配空间;否则ch=NULL
int length;//串长度
}HString;
3.串的链式存储结构
#define CHUNSIZE 80//自定义块的大小
typedef struct Chunk{//定义块类型
char ch[CHUNSIZE];
struct Chunk *next;
}Chunk;
typedef struct{//定义串类型
Chunk *head,*tail;//串的头指针和尾指针
int length; //串的当前长度
}LString
二、串的模式匹配算法
BF算法

Status BF(Sstring S,SsTring T,int pos){
    int i,j=1;
    i=pos;
    while(i<S[0] && j<=T[0]){
       if(i<=S[0] && j<=T[0]){++i;++j;}
       else{i=i-j+2;j=1;}//回溯操作
    }
    if(j>T[0])return i-T[0];
    else return 0;
}

KMP算法

Status Index_KMP(SString S,SString T,int pos){
     i=pos;j=1;
     while(i<=s[0] && j<=T[0]){
      if(j==0 || s[i]==s[j]){++i;++j;}//不失配则继续比较后续字
      else{j=next[j];}//S的i指针不回溯,从T的k位置开始匹配  
     } 
     if(j>T[0])return i-T[0];//子串结束,说明匹配成功
     else return 0;     
}
void GetNext(String T,int next[]){
     int j,k;
     j=1;k=0;
     next[j]=k;
     while(j<T[0]){//T[0]表示字符串长度
       //当k=0时,j+1的next是k+1,即1;
       //当T[k]=T[j]   j+1的next是k+1
       if(k==0 || T[k]==T[j]){
           ++j;
           ++k;
           next[j]=k;
       }
       else
           k=next[k];
     } 
}
void GetNextVal(Sstring T,int nextval[]){
     int j=1,k=0;
     nextval[j]=k;
     while(j<T[0]){
        if(k==0 || T[j]==T[k]){
           j++;k++;
           if(T[j]!=T[k])
              nextval[j]=k;
           else
              nextval[j]=nextval[k];
        }
        else k=nextval[k];
     }
}
nextval[j]计算步骤  (1)计算出next[j] = k值,
                    (1.1)如果Tj = Tk ,nextval[j] = nextval[k]
                     (1.2) 如果Tj != Tk,nextval[j] = next[j] = k.
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值