数据结构实验2———线性表及其应用

本文介绍了顺序表和单链表的基本操作,包括建立、输出、求长度、查找、插入、删除等,并实现了菜单驱动程序。程序包括顺序表的逆置、删除指定值元素、有序表合并等功能,以及单链表的查找最大值结点、逆置、删除特定范围元素等操作。
摘要由CSDN通过智能技术生成

    • 实验内容

    (1)编程实现顺序表的如下操作,并设计菜单完成调用。

    ①表的建立、输出、求长度、取值、查找、插入、删除等基本操作(必做)

    ②表的逆置(要求利用原表的存储空间)。(选做)

    ③删除表中所有值为x的元素。(选做)

    ④将两个递增有序表合并成一个递增有序表。(算法2.16,P43)【考虑:数据不重复,或者合并为递减有序表的情况)】

    (2)编程实现单链表的如下操作,并设计菜单完成调用。

    ①表的建立、输出、求长度、取值、查找、插入、删除等基本操作(必做)

    ②通过一次遍历确定表中值最大(或最小)的结点。(习题2.6,P53)。(必做)

    ③表的逆置(要求利用原表的存储空间)。(习题2.7,P53)。(选做)

    ④删除表中数据值大于mink且小于maxk的所有结点。(习题2.8,P53)

    ⑤将两个递增有序表合并成一个递增有序表。(算法2.17,P44)【考虑:数据不重复,或者合并为递减有序表的情况)】(选做)

    (3)编程实现单循环链表或双向(循环)链表的基本操作(如:建立、输出、求长度、取值、查找、插入、删除等),并设计一个菜单调用。(选做)

 

  1. 编程实现顺序表的基本操作,并设计一个菜单调用。
  1. 程序结构、核心代码:
  • comdef.h
  •  #include <stdio.h>
       #include <iostream>
       using namespace std;
       #define OK 1
       #define ERROR 0
       #define OVERFLOW -1
       typedef int Status;
  • sqlistdef.H
  • //顺序表的存储结构 

    #define MAXSIZE 100 //顺序表可能达到的最大长度  
    typedef int ElemType;
    typedef struct
    {
            ElemType *elem;        //存储空间的基地址 
            int length;   //当前长度 
    }SqList;//顺序表的结构类型 

  • sqlistapp.H

//顺序表的初始化

Status InitList(SqList  &L)

{

      int i,n;

      L.elem=new ElemType[MAXSIZE]; //为顺序表动态分配一个大小为MAXSIZE的数组空间

        if (!L.elem) return OVERFLOW;       //分配失败则退出

    cout<<"\n数据个数=";

      cin>>n;

      cout<<"\n输入"<<n<<"个数据: ";

    for (i=0;i<n;i++)

        cin>>L.elem[i];

     L.length=n;

     return OK;

}

//表的输出

void OutputList(SqList L){

    int i;

    for (i=0;i<L.length;i++)        //依次访问顺序表(数组)的元素 ,输出

        cout<<" "<<L.elem[i];

    cout<<endl;

}

 //表的求长度

int ListLength(SqList L)

{              

        return L.length;

}

//判断非空

bool ListEmpty(SqList L)

 {

       return L.length==0;

 }

 //取值

 Status GetElem(SqList L,int i,ElemType &e)

 {

       if(i<1||i>L.length) //判断位置的合法性

         return ERROR;

         

       e=L.elem[i-1];//取表中序号为i的元素的值并用e带出

       return OK;

 }

//查找,此算法平均时间复杂度为O(n)

 int LocateElem(SqList L,ElemType e)

 {

       for(int i=0;i<L.length;i++)

       {

                if(L.elem[i]==e)      //查找表中与e相等的元素,并返回它的序号

                        return i+1;

        }

         return 0;

  }

//表的插入

Status ListInsert(SqList &L,int i,ElemType e)//在第i个位置插入新元素e

{

        int j;

        if(i<1||i>L.length+1) return ERROR; // 判断插入位置的合法性

        if(L.length==MAXSIZE) return ERROR;//判断储存空间是否已满

        for(j=L.length-1;j>=i-1;j--)  //将第i至第n个位置的元素依次后移

        {

                 L.elem[j+1]=L.elem[j];

                

        }

         L.elem[i-1]=e;      //空出第i个位置,赋值

         ++L.length;// 表长加一

         return OK;

}

//表的删除

Status ListDelete(SqList &L,int i)

{

        if(i<1||i>L.length) //判断删除位置的合法性

        return ERROR;

        for(int j=i;j<L.length;j++)

        {

                 L.elem[j-1]=L.elem[j];//被删除元素之后的元素依次前移

       

        }

        --L.length;//表长减一

        return OK;

}

//表的逆置

void ListRervese(SqList &L)

{

        ElemType temp;

        int i,j;

        for(i=0,j=L.length-1;i<j;i++,j--)//由外向内,表两头的元素依次互换

        {

                 temp=L.elem[i];

                 L.elem[i]=L.elem[j];

                 L.elem[j]=temp;

        }

 }

//删除表中所有值为e的元素(时间复杂度为O(n)、空间复杂度为O(1)

Status DeleteE(SqList &L,ElemType e)

{

        int k=0;

        for(int i=0;i<L.length;i++)

        {

                 if(L.elem[i]!=e)

                 {

                         L.elem[k]=L.elem[i];//将数组中不为e的元素,覆盖原来值为e的元素

                         k++;

                 }

        }

        //判断是否成功删除了表中与e相同的元素

        if(k!=L.length){

                 L.length=k;

        } else{

                 return ERROR;    

        }

}

//有序表的合并

void MergeList_Sq(SqList L,SqList LA,SqList &LB,int &n)

{

        //将两个递增的有序表LLA合并成一个递增的有序表LB

        ElemType *p,*pa,*pb,*p_last,*pa_last;

        LB.length=L.length+LA.length;

        LB.elem=new ElemType[LB.length];//为表LB动态分配空间

        pb=LB.elem;

        //ppa分别指向两表的首元素

        p=L.elem;

        pa=LA.elem;

        n=0;//两表中相同元素的个数

        //p_lastpa_last分别指向两表的最后一个元素

        p_last=L.elem+L.length-1;

        pa_last=LA.elem+LA.length-1;

        //LALB均未达到表尾时

        while((p<=p_last)&&(pa<=pa_last))

        {

                 //依次摘取值较小的插入LB的最后

                 if(*p<*pa)

                 {

                         *pb++=*p++;

                 }

                 else if(*p>*pa)

                 {

                         *pb++=*pa++;

                 }

                 //两值相等时取L的值

                 else

                 {

                         *pb++=*p++;

                         *pa++;

                         n++;

                 }

        }

        while(p<=p_last) *pb++=*p++;// LA已达到表尾,依次将L的剩余元素插入LB的最后

        while(pa<=pa_last) *pb++=*pa++;//L已达到表尾,依次将LA的剩余元素插入LB的最后

}

//表的摧毁

void DestroyList(SqList &L)

{

        delete []L.elem;

        L.elem=NULL;

        L.length=0;   

}

  • main.CPP

int main()

{

        SqList L;

        ElemType e;

        int choice,i;   

        cout<<"\n建立数据表:";

        if (InitList(L)==OVERFLOW)

        {

                cout<<"数据表空间分配失败,程序退出!";

                  return 0;

        }

        else

        {

              cout<<"数据表建立成功,数据表为:";

              OutputList(L);

        }

        //菜单

        do

        {

                 cout<<"\n\n===================================";

                 cout<<"\n        顺序表的基本操作           ";

                 cout<<"\n===================================";

                 cout<<"\n       1:表的输出" ;

                 cout<<"\n       2:求表的长度" ;

                 cout<<"\n       3:判断空表" ;

                 cout<<"\n       4:取表中元素" ;           

                 cout<<"\n       5:查找表中元素" ;

                 cout<<"\n       6:插入元素" ;

                 cout<<"\n       7:删除元素" ;

                 cout<<"\n       8:表的逆置" ;

                 cout<<"\n       9:删除表中为e的元素" ;

                 cout<<"\n       10:将两个递增的有序表LLA合并成一个递增的有序表LB" ;

                 cout<<"\n       0:操作结束" ;

                 cout<<"\n===================================";

                 cout<<"\n请输入你的选择:";

                 cin>>choice;

                 switch (choice)

                {

                         case 1:     cout<<"\n数据表为:";

                                          OutputList(L);

                                  break;

                         case 2:     cout<<"\n数据表的长度为:"<<ListLength(L);

                                  break;

                         case 3:     if( ListEmpty(L))

                                                  cout<<"\n数据表为空表";

                                          else

                                          cout<<"\n数据表为非空表";

                                  break;           

                         case 4:

                                          cout<<"输入位置";     

                                          cin>>i;

                                          if(!GetElem(L,i,e))

                                                  cout<<"\n位置不合法";

                                          else

                                                  cout<<"\n取值成功,第"<<i<<"个位置的元素是"<<e;

                                          break;

                         case 5:    

                                  cout<<"\n输入待查找的数据:";

                                  cin>>e;                            

                                  if(!LocateElem(L,e))

                                  cout<<"\n查找失败";

                                   else

                                  cout<<"\n查找成功,"<<e<<"在数据表中第"<<LocateElem(L,e)<<"个位置";

                                          break;

                         case 6:     cout<<"\n插入元素的位置和值";

                                          cin>>i>>e;

                                          if(ListInsert(L,i,e))

                                          {

                                                  cout<<"\n插入成功!";

                                                  cout<<"\n插入后的数据表为:";

                                                  OutputList(L);

                                           }

                                           else

                                           cout<<"\n插入位置不合法或储存空间已满";

                                          break;

                         case 7:     cout<<"\n删除元素的位置";

                                          cin>>i;

                                          if(ListDelete(L,i))

                                          {

                                                  cout<<"\n删除成功!";

                                                  cout<<"\n删除后的数据表:";

                                                  OutputList(L);

                                           }

                                           else

                                           cout<<"\n插入位置不合法";

                                          break;

                         case 8:ListRervese(L);

                                          cout<<"逆置后的数据表为:";

                                           OutputList(L);

                                break;

                         case 9:cout<<"需要删除的元素为:";

                                 cin>>e;

                                 if((DeleteE(L,e))==ERROR)

                                 {

                                         cout<<"\n表中无该元素";

                                          }

                                 else

                                          {

                                                  cout<<"\n删除成功!";

                                                  cout<<"\n删除后的数据表:";

                                                  OutputList(L);

                                           }

                                          break;

                         case 10: SqList LA,LB;

                                           int n;

                                           cout<<"\n建立数据表LA";

                                           if (InitList(LA)==OVERFLOW){

                               cout<<"数据表空间分配失败,程序退出!";

                                    return 0;

                                           }else{

                                                cout<<"数据表建立成功,数据表为:";

                                                OutputList(LA);

                                           }

                                           MergeList_Sq(L,LA,LB,n);

                                           cout<<"\n合并后的数据表为:";

                                           for(i=0;i<LB.length-n;i++)

                                           {

                                                 cout<<LB.elem[i]<<" ";

                                           }

                                           break;

                         case 0:     break;

                         default:cout<<"\n输入错误,重新输入!";                       

                }

        } while (choice) ;   

        DestroyList(L);

        return 0;

}

2. 编程实现单链表的基本操作,并设计一个菜单调用。

1)程序结构、核心代码:

comdef.h

#include <stdio.h>
   #include <iostream> 
   using namespace std;
   #define OK 1
   #define ERROR 0
   #define OVERFLOW -1
   typedef int Status;
   

linkkistdef.H

typedef int ElemType;
//单链表的存储结构 
typedef struct LNode
{
    ElemType data;//结点的数据域 
    struct LNode *next;//结点的指针域 
}LNode,*LinkList;    //LinkList为指向结构体LNode的指针类型 

linklistaoo.H

//建立单链表(后插法) ,该算法时间复杂度为O(n)

Status InitList(LinkList& L)

{

        LinkList p,r;

       int i,n;

      L=new LNode; //生成新结点作为头结点,用头指针L指向头结点     

        L->next=NULL;//建立一个带头结点的空链表

        r=L;//尾指针r指向头结点

        cout<<"\n数据个数=";

      cin>>n;

      cout<<"\n输入"<<n<<"个数据: ";

    for (i=0;i<n;i++)

        {

            p=new LNode;  //生成新结点

            cin>>p->data;//输入元素值赋给新结点的数据域

                 r->next=p;

            p->next=NULL;//将新结点*p插在表尾

            r=p;   //修改尾指针

        }   

    return OK;

}

//输出单链表 ,该算法时间复杂度为O(1) 

void  OutputList(LinkList L)

{

        LinkList p;

        p=L->next;//头结点指向p

        while (p)

        {

                 cout<<"  "<<p->data;

                 p=p->next;

        }

}

//表的求长度,该算法时间复杂度为O(1) 

Status ListLength(LinkList L)

{

        int j=0;

        LinkList p;

        p=L->next;

        while(p)

        {

                 j++;

                 p=p->next;

        }

        return j;

}

//判断非空,该算法时间复杂度为O(1) 

bool ListEmpty(LinkList L )

{

       

        return L->next==NULL;

}

//取表中元素,该算法时间复杂度为O(n) 

Status GetElem(LinkList L,int i,ElemType &e)

{

        //取第i个结点的值,并用e保存此数据域

        LinkList p;

        p=L->next;//初始化,p指向首元结点

        int j=1;//计数器赋值为1

        while(p&&j<i)       //顺链域向后扫描,直到p为空或p指向第i个元素

        {

                 p=p->next;//p指向下一个结点

                 ++j;

        }

        if(!p&&j>i)// 判断i的合法性

        {

                 return ERROR;

        }

        e=p->data;//取第i个结点的数据域

        return OK;

}

 //查找表中元素,该算法时间复杂度为O(n) 

Status LocateElem(LinkList L,ElemType e)

{

        LinkList p;

        p=L->next;//初始化,p指向首元结点

        //int i=1;//计数器赋值为1

        while(p && p->data!=e)//顺链域向后扫描,直到p为空或p所指结点的数据域等于e

        {

                 p=p->next;

        //i++;

        }

        //if(!p) return 0;

        //else return i;

        return p;

}

//插入元素,该算法时间复杂度为O(n) 

Status ListInsert(LinkList &L,int i,ElemType e)

{

        //将数据域为e的新结点插入第i个结点的位置上(在结点i-1i之间)

        LinkList s,p;

        p=L;

        int j=0;

        while(p && (j<i-1))//查找第i-1个结点(该位置的前驱结点),p指向该结点

        {

                 p=p->next;

                 ++j;

        }

        //判断i的值是否合法

        if(!p||j>i-1) return ERROR;// 判断i的合法性

        s=new LNode;//生成一个数据域为e的新结点*s 

        s->data=e;

        s->next=p->next;//将结点*s的指针域指向第i个结点

        p->next=s;//将结点*p的指针域指向结点*s

        return OK;

}

 //删除元素,该算法时间复杂度为O(n) 

Status ListDelete(LinkList &L,int i,ElemType &e)

{

        LinkList p,q;

        p=L;

        int j=0;

        while((p->next)&&(j<i-1))//查找第i-1个结点(该位置的前驱结点),p指向该结点

        {

                 p=p->next;

                 ++j;

        }

        //判断i位置是否合理

        if(!(p->next)||(j>i-1)) return ERROR;

        q=p->next;//q临时保存被删结点的地址以备释放

        e=q->data;

        p->next=q->next;//改变删除结点前驱结点的指针域

        delete q;//释放删除结点的空间

        return OK;

}

//获取表中元素值最大的结点的位置

Status MaxNode(LinkList L)

{

    LinkList p = L->next;

    int max=p->data;

    int i = 1,maxnode;

    while(p)

        {

        if(p->data >max)//当前结点的数据域与最大元素值相比

                 {

            max = p->data;

            maxnode = i;

        }

            p = p->next;

        ++i;

    }

    return maxnode;

}

//逆置单链表(用头插法思想)

void ReverseList(LinkList &L)

{

        LinkList p,q;//q指向次首元结点,p指向首元结点

        p=L->next;

        L->next=NULL;

        while(p)

        {

                 q=p;//q指向将被逆序链接的结点

                 p=p->next;//q指向下一结点

                 /*头插法 */

                 q->next=L->next;

                 L->next=q;

        }

}

//删除表中比mink大且比maxk小的结点

Status DeleteNode(LinkList &L,ElemType mink,ElemType maxk)

{

        LinkList p,q;//p为首元结点,q为头结点

        p=L->next;

        q=L;

        if(mink>=maxk)//判断minkmaxk的输入是否合理

        {

                 return ERROR;

        }

        else

        {

                 while(p!=NULL)

                 {

                         if((p->data>mink)&&(p->data<maxk))

                         {

                                  q->next=p->next;//满足条件则删除p结点

                                  //释放空间

                                  delete(p);

                                  p=q->next;

                         }

                         else

                         { 

                             //若不满足条件则pq后移一位

                                  q=q->next;

                                  p=p->next;

                         }

                 }

                 return OK;

        }

}

//合并两个递增有序单链表LLA为一个LB

void MergeList_L(LinkList &L,LinkList &LA,LinkList &LB){

        LinkList p,pa,pb;

        //pap的初值分别指向两个表的首元结点

        p=L->next;

        pa=LA->next;

        LB=L; //L的头结点做为LB的头结点

        pb=LB;//pb的初值指向LB的头结点

        while(p&&pa)

        {

                 //LLA均未达到表尾,依次摘取较小结点插入LB的最后

                 if((p->data)<(pa->data)){

                         pb->next=p;

                         pb=p;

                         p=p->next;

                 }else if((p->data)>(pa->data)){

                         pb->next=pa;

                         pb=pa;

                         pa=pa->next;

                 }else

                 {

                         pb->next=p;

                         pb=p;

                         p=p->next;

                         pa=pa->next;//相等时摘取L的结点,但同时pa也需后移

                 }

        }

        //将非空表的剩余部分插入到pc所指结点之后

        pb->next=p?p:pa;

        delete LA;

}

//摧毁单链表

Status DestroyList(LinkList &L)

{

        LinkList p;

        while (L)

        {

         p=L; 

        L=L->next;

        delete p;

        }

        L=NULL;

    return OK;

}

main.CPP

#include "comdef.h"

#include "linklistdef.h"

#include "linklistapp.h"

int main(){

        LinkList L;

        int i;

        ElemType e,maxnode,minnode,mink,maxk;

        int choice;      

        cout<<"\n建立数据表:";

        if (InitList(L)==OVERFLOW){

                cout<<"数据表空间分配失败,程序退出!";

                  return 0;

                  }

        else{

              cout<<"数据表建立成功,数据表为:";

              OutputList(L);

        }

        do {

                 cout<<"\n\n===================================";

                 cout<<"\n        单链表的基本操作           ";

                 cout<<"\n===================================";

                 cout<<"\n       1:表的输出" ;

                 cout<<"\n       2:求表的长度" ;

                 cout<<"\n       3:判断空表" ;

                 cout<<"\n       4:取表中元素" ;           

                 cout<<"\n       5:查找表中元素" ;

                 cout<<"\n       6:插入元素" ;

                 cout<<"\n       7:删除元素" ;

                 cout<<"\n       8:获取数据值最大的节点" ;

                 cout<<"\n       9:表的逆置" ;

                 cout<<"\n       10:删除表中数据值大于mink且小于maxk的所有结点" ;

                 cout<<"\n       11:合并两个递增有序表为一个递增有序表(数据不重复)" ;

                 cout<<"\n       0:操作结束" ;

                 cout<<"\n===================================";

                 cout<<"\n请输入你的选择:";

                 cin>>choice;

                 switch (choice){

                 case 1:     cout<<"\n单链表为:";

                                          OutputList(L);

                                     break;

                         case 2:     cout<<"\n单链表的长度为:"<<ListLength(L);

                                     break;

                         case 3:     if(ListEmpty(L)==OK){

                                                  cout<<"\n该表是空表";

                                          }else{

                                                  cout<<"\n该表不是空表";

                                          }

                                     break;             

                         case 4:     cout<<"\n所取元素的序号为:";

                                          cin>>i;

                                          if((GetElem(L,i,e))==ERROR){

                                                  cout<<"\n输入不合法!";

                                          }else{

                                                  cout<<"\n取出的元素值为:"<<e;

                                          }

                                          break;

                         case 5:     cout<<"\n输入查找元素的值:";

                                          cin>>e;

                                          i=LocateElem(L,e);

                                          if(i==0){

                                                  cout<<"\n查找失败!";

                                          }else{

                                                  cout<<"\n"<<e<<"在表中位于第"<<i<<"";

                                          }

                                          break;

                         case 6:     cout<<"\n输入插入的元素的位置以及元素的值:";

                                          cin>>i>>e;

                                          if((ListInsert(L,i,e))==ERROR)

                                          {

                                                  cout<<"\n插入失败,输入的值不合法!";

                                          }else

                                          {

                                                  cout<<"\n插入成功,数据表为:";

                                                  OutputList(L);

                                          }

                                          break;

                         case 7:     cout<<"\n输入删除的元素的位置:";

                                          cin>>i;

                                          if((ListDelete(L,i,e))==ERROR)

                                          {

                                                  cout<<"\n输入的位置不合理!";

                                          }else{

                                                  cout<<"\n删除成功,删除的元素是:"<<e;

                                                  cout<<"\n删除后的数据表为:";

                                                  OutputList(L);

                                          }

                                          break;

                         case 8: cout<<"\n表中数据元素最大值对应的节点为:"<<MaxNode(L);

                                          break;

                         case 9: cout<<"\n逆置后的数据表为:";

                                          ReverseList(L);

                                          OutputList(L);

                                          break;

                     case 10:cout<<"\n输入mink的值:";

                                          cin>>mink;

                                          cout<<"\n输入maxk的值:";

                                          cin>>maxk;

                                          if((DeleteNode(L,mink,maxk))==ERROR){

                                                  cout<<"\n输入值不合法!";

                                          }else{

                                                  cout<<"\n删除后数据表为:";

                                                  OutputList(L);

                                          }

                                          break;

                         case 11:LinkList LA,LB;

                                          cout<<"\n建立数据表LA";

                                          if (InitList(LA)==OVERFLOW){

                                                  cout<<"数据表空间分配失败,程序退出!";

                                                  return 0;

                                          }

                                          else{

                                                  cout<<"数据表建立成功,数据表为:";

                                                  OutputList(LA);

                                          }

                                          MergeList_L(L,LA,LB);

                                          cout<<"\n合并后的数据表L为:";

                                          OutputList(L);

                                          break;

                         case 0:     break;

                         default:cout<<"\n输入错误,重新输入!";                       

                 }

        } while (choice) ;   

        DestroyList(L);     

        return 0;

}

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值