你需要打好线性表的基础——数据结构

引言:

    我们都知道,盖房子需要坚实的基础,作为一个学完数据结构的弱鸡,我真切的感到了基础的力量。排开那些基本的概念,那些算法计算的表达。我们之后的大部分操作,都是建立在线性表的基础上,所以我们要学会利用这两大工具——顺序表和链表。只有掌握了它们,之后所有的算法才可以去谈实现,不然都是纸上谈兵(当然啦,会算法也很重要)。那么我们一起来学习吧,所有的讲解都是按照:初始化、取值、查找、插入、删除(创建---这里链表才有)这个线性方式。这里可以给出一个目录,方便大家进行阅读。

目录

一、顺序表

二、单链表

三、循环链表和双向链表简单介绍


一、顺序表

1.初始化

【算法步骤】

  • 为顺序表L动态分配一个预定义大小的数组空间,使elem指向这段空间的基地址。
  • 将表的当前长度设为0。

【算法描述】

void InitList(SqList &L)
{//构造一个空的顺序表L
    L.elem = new ElemType[MAXSIZE];//为顺序表分配一个大小为MAXSIZE的数组空间
    if(!L.elem) exit(OVERFLOW);//存储分配失败退出
    L.length = 0;//空表长度为0
}

2.取值

【算法步骤】

  • 判断指定的位置序号i值是否合理(1<=i<=L.length),若不合理,则返回ERROE。
  • 若i值合理,则将第i个数据元素L.elem[i-1]赋给参数e,通过e返回第i个数据元素的传值。

【算法描述】

int GetElem(SqList L,int i,ElemType &e)
{
    if(i<1||i>L.length) return ERROR;//判断i值是否合理,若不合理,返回ERROR
    e = L.elem[i-1];//elem[i-1];//elem[i-1]单元存储第i个数据元素
    return e;
}

3.查找

【算法步骤】

  • 从第一个元素起,依次和e相比较,若找到与e相等的元素L.elem[i],若查找成功,返回该元素的序号i+1。
  • 若查遍整个顺序表都没有找到,则查找失败,返回0。

【算法描述】

int LocateElem(SqList L,ElemType e)
{//在顺序表L中查找值为e的数据元素,返回其序号
    for(i=0;i<;.length;i++)
        if(L.elem[i]==e) return i+1;//查找成功,返回序号i+1
     return 0;//查找失败
}

4.插入

【算法步骤】

  • 判断插入位置i是否合法(i值的合法范围是1<=i<=n+1),若不合法则返回ERROR
  • 判断顺序表的存储空间是否已满,若满则返回ERROR
  • 将第n个至第i个位置的元素依次向后移动一个位置,空出第i个位置(i=n+1时无需移动)
  • 将要插入的新元素e放入第i个位置
  • 表长加1

【算法描述】

void ListInsert(Sqlist &L,int i,ElemType e)
{//在顺序表L中第i个位置插入新的元素e,i值的合法范围是1<=i<=L.length+1
    if((i<1)||(i>L.length+1) return ERROR;//i值不合法
    if(L.length==MAXSIZE) return ERROR;//当前储存空间已满
    for(j=L.length-1;j>=i-1;j--)
        L.elem[j+1]=L.elem[j];//插入位置及之后的元素后移
    L.elem[i-1]=e;//将新元素e放入第i个位置
    ++L.length;//表长加1
}

5.删除

【算法步骤】

  • 判断删除位置i是否合法(合法值为1<=i<=n),若不合法则返回ERROR。
  • 将第i+1个至第n个元素依次向前移动一个位置(i=n时无需移动)
  • 表长减1

【算法描述】

void ListDelete(SqList &L,int i)
{//在顺序表L中删除第i个元素,i值的合法范围是1<=i<=L.length
   if((i<1)||(i>L.length)) return ERROR;	 //i值不合法
   for (j=i; j<=L.length-1; j++)                   
    L.elem[j-1]=L.elem[j];   //被删除元素之后的元素前移  
   --L.length;               	      //表长减1
}

 

二、单链表

1.初始化

【算法步骤】

  • 申请头结点,用头指针L指向头结点。
  • 头结点的指针域置空。

【算法描述】

void InitList(LinkList &L)
{//构造一个空的单链表L 
   L=new  LNode;//生成新结点作为头结点,用头指针L指向头结点                    	
   L->next=NULL;     //头结点的指针域置空
} 

2.取值

【算法步骤】

  • 用指针p指向首元结点,用j做计数器初值赋为1
  • 从首元结点开始依次顺着链域next向下访问,只要指向当前结点的指针p不为空(NULL),并且没有到达序号为i的节点,则循环执行以下操作:

            p指向下一个结点

            计数器j相应加1

  • 退出循环时,如果指针p为空,或者计数器j大于i,说明指定的序号i值不合法(i大于表长n或i小于等于0),取值失败返回ERROR;否则取值成功,此时j=i时,p所指的结点就是要找的第i个结点,用参数e保存当前结点的数据域,返回数值。

【算法描述】

int GetElem(LinkList L, int i, ElemType &e)
{//在带头结点的单链表L中根据序号i获取元素的值,用e返回L中第i个数据元素的值 
    p=L->next;j=1; //初始化
     while(p&&j<i)    //向后扫描,直到p指向第i个元素或p为空 
     { 
       p=p->next;   ++j; 
     } 
     if(!p || j>i)   return ERROR;     //第i个元素不存在 
     e=p->data;     //取第i个元素,e带回 
     return e; 
}

3.查找

【算法步骤】

  • 用指针p指向首元结点
  • 从首元结点开始依次顺着链域next向下查找,只要指向当前节结点的指针p不为空,并且p所指结点的数据域不等于给定值e,则循环执行以下操作:p指向下一个节点
  • 返回p。若查找成功,p此时即为结点的地址值,若查找失败,p的值即为NULL

【算法描述】

LNode *LocateELem_L (LinkList L,Elemtype e)
{ //在带头结点的单链表L中查找值为e的元素
  p=L->next;//初始化,p指向首元结点
  while(p &&p->data!=e)  //顺链域向后扫描,直到p为空或p所指结点的数据域等于e
        p=p->next;        //p指向下一个结点        		
  return p; 	//查找成功返回值为e的结点地址p,查找失败p为NULL
} 

4.插入

【算法步骤】

  • 查找结点a(i-1)并由指针p指向该结点
  • 生成一个新结点*s
  • 将新结点*s的数据域置为e
  • 将新结点*s的指针域指向结点ai
  • 将结点*p的指针域指向新结点*s

【算法描述】

void ListInsert(LinkList &L,int i,ElemType e){ 
     p=L;j=0; 
    while(p&&j<i−1)  
        {p=p->next;++j;} //寻找第i−1个结点 
     if(!p||j>i−1)   return ERROR; //插入位置不合理
      s=new LNode;			//生成新结点s 
      s->data=e;      		          //将结点s的数据域置为e 
      s->next=p->next;	         //将结点s插入L中 
      p->next=s;  
}

5.删除

【算法步骤】

  • 查找结点a(i-1)并由指针p指向该结点
  • 临时保存待删除结点ai的地址在q中,以备释放
  • 将结点*p的指针域指向ai的直接后继结点
  • 释放结点ai的空间

【算法描述】

void ListDelete(LinkList &L,int i,ElemType &e)
{//在带头结点的单链表L中,删除第i个元素
    p=L; j=0; 
    while( p->next &&j<i-1) //寻找第i-1个结点
    {  p=p->next;   ++j;     } 
    if(!(p->next)||j>i-1)   return ERROR; //删除位置不合理 
    q=p->next;    //临时保存被删结点的地址,以备释放空间 
    p->next=q->next;   //修改前驱结点的指针域 
    delete q; 	 //释放删除结点的空间  
}

6.创建

①前插法创建单链表

【算法步骤】

  • 创建一个只有头结点的空链表
  • 根据待创建链表的元素个数n,循环n次以下操作:                                                                                                                            生成一个新结点, 由p指向;       给新结点的数据域输入元素值;       将新结点插入到头结点之后.

【算法描述】

void CreateList_F(LinkList &L,int n)
{//逆位序输入n个元素的值,建立带表头结点的单链表L 
      L=new LNode; 
      L->next=NULL; //建立一个带头结点的单链表 
      for(i=0;i<n;++i) 
      { 
        p=new LNode; //生成新结点 
        cin>>p->data; //输入元素值 
        p->next=L->next;
        L->next=p; 	   //插入到表头 
     } 
}

②后插法创建单链表

【算法步骤】

  •    创建一个只有头结点的空链表
  •    将辅助尾指针 r 初始化,使其指向头结点   
  •    根据待创建链表包括的元素个数n,循环以下操作:                                                                                                                                生成一个新结点,由p指向;       给新结点的数据域输入元素值;       将新结点插入到尾结点r之后      尾指针r改为指向新的尾结点

【算法描述】

void CreateList_L(LinkList &L,int n)
{ //正位序输入n个元素的值,建立带表头结点的单链表L 
      L=new LNode; 
      L->next=NULL;//先建立一个带头结点的空链表 	
      r=L; 	//尾指针r初始指向头结点 
      for(i=0;i<n;++i)
      { 
        p=new LNode;	 	//生成新结点 
        cin>>p->data;   		//输入元素值 
        p->next=NULL; r->next=p;    	//插入到表尾 
        r=p; 	//让r指向新的尾结点 
      } 
}

 

三、循环链表和双向链表简单介绍

【循环链表】

单链表循环条件:          单向循环链表循环条件:
p!=NULL                             p!=L              (不带头结点) 
p->next!=NULL                   p->next!=L        (带头结点)

【双向链表】

结构体:

typedef struct DuLNode{    

ElemType   data;                  

struct DuLNode  *prior;      

struct DuLNode  *next;  

}DuLNode, *DLinkList

相关操作:

①插入

Status ListInsert_DuL(DuLinkList&L,int i,ElemType e)
{  if( ! (p=GetElemP_DuL(L,i) ) )  return ERROR;
    s=new DuLNode; 
   s->data=e;
   s->prior=p->prior;  
   p->prior->next=s;
   s->next=p;  
   p->prior=s;
   return OK;
}

  ②删除

Status ListDelete_DuL(DuLinkList &L,int i)
{
   if(!(p=GetElemP_DuL(L,i)))     return ERROR;
   p->prior->next=p->next;
   p->next->prior=p->prior;
   delete p; 
   return OK;
}

 

后记:

     如果有误评论指出,谢谢,建议写一个图书管理系统或者多项式相加来熟悉相关的操作。

发布了93 篇原创文章 · 获赞 193 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43919400/article/details/103683002