【数据结构】第二章 线性表

1.线性表的定义和特点

  • 存在唯一一个“第一个”元素
  • 存在唯一一个“最后一个”元素
  • 除第一个元素外,每一个元素都有且只有一个直接前驱
  • 除最后一个元素外,每个元素都有且只有一个直接后继

2.线性表的顺序表示

3.线性表的链式表示

4.实验报告

(1) 编程实现顺序表的基本操作(建立、插入、删除、输出、顺序查找、折半查找、排序等),并设计一个菜单调用。

com_def.h

#include <stdio.h> 
#include <iostream>
#include <iomanip>
#include <string.h>
#include <malloc.h>
#include <process.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
typedef int Status;

sqlist_def.h

#define LIST_INIT_SIZE 100//线性表存储空间的初始分配量
#define LISTINCREMENT 10//线性表存储空间的分配增量
typedef int ElemType;
typedef struct{
 ElemType *elem; //存储空间的首地址
 int length; //当前长度 
 int listsize; //当前分配的存储容量 
}Sqlist;

sqlist_func.h

#include "com_def.h"
using namespace std;
Status InitList_Sq(Sqlist &L);
Status ListInsert_Sq(Sqlist &L,int i,ElemType e);
Status Show(Sqlist L);
Status GetElem(Sqlist L, int i,ElemType &e);
Status LocateElem(Sqlist L, ElemType e);
Status BubbleSort(Sqlist L);
Status Binary_Search(Sqlist &L, int &i,ElemType e);

Status InitList_Sq(Sqlist &L){
 //构造一个空的线性表
 int n,i;
 L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
 if(!L.elem) exit(OVERFLOW);  //存储分配失败
 cout<<endl<<"请输入元素个数:";
 cin>>n;
 cout<<"请输入这"<<n<<"个元素:"<<endl;
 for(i=0;i<n;i++){
  cin>>L.elem[i];
 }
 
 L.length=n;//空表长度为 0 
 L.listsize=LIST_INIT_SIZE;//初始存储容量
 return OK; 
}
Status ListInsert_Sq(Sqlist &L,int i,ElemType e){
 //在顺序线性表L中第i个位置之前插入新的元素e
 //i的合法值为1<=i<=ListLength_sq(L)+1
 ElemType *p;
 if(i<1||i>L.length+1) return ERROR;//i值不合法
 if(L.length>=L.listsize){
  //当前存储空间已满,请重新分配内存
  ElemType *newbase=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
  if(!newbase) exit(OVERFLOW);//存储分配失败 
  L.elem=newbase;//新的首地址 
  L.listsize+=LISTINCREMENT;//增加存储容量 
 }
 ElemType *q=&(L.elem[i-1]);//q为插入位置的地址 
 for(p=&(L.elem[L.length-1]);p>=q;--p){
  *(p+1)=*p;//插入位置及之后的元素右移  
 } 
 *p=e;//插入e
 ++L.length;//表长增加1
 return OK;
  
}

Status ListDelete_Sq(Sqlist &L,int i,ElemType &e){
 //在顺序线性表L中删除第i个元素,并用e值返回
 //i的合法值为1<=i<=ListLength_Sq(L)
 ElemType *p,*q;
 if(i<1||i>L.length) return ERROR;//i的值不合法
 p=&(L.elem[i-1]);//p为删除元素的位置
 e=*p;//被删除的元素的值赋给e
 q=L.elem+L.length-1;//表尾元素的位置
 for(++p;p<=q;++p){
  //被删除元素之后的元素左移 
  *(p-1)=*p; 
 } 
 --L.length;//表长减一 
 return OK; 
  
}

Status Show(Sqlist L)
{
 int i;
 cout<<"此时表中现有的元素为:\n";
 for(i=0;i<L.length;i++)
 {
  cout<<L.elem[i]<<endl;
 }
}

Status GetElem(Sqlist L, int i,ElemType &e)
{
 
 if(i<1||i>L.length) return ERROR;
 e=L.elem[i-1];
 return OK; 
}

Status LocateElem(Sqlist L, ElemType e){
 int i;
 ElemType *p;
 i=1;
 p=L.elem;
 while(i<=L.length&&*p!=e){
  ++i;
  p++;
 }
 if(i<=L.length) return i;
 else return 0;
}

Status BubbleSort(Sqlist L){
 //冒泡排序 
 int i,j;
 ElemType temp;
 for(i=0;i<L.length;i++)
 {
  for(j=1;j<L.length-i;j++)
  {
   if(L.elem[j-1]>L.elem[j])
   {
    temp=L.elem[j];
    L.elem[j]=L.elem[j-1];
    L.elem[j-1]=temp;
   }
  }  
 }
}

Status Binary_Search(Sqlist &L, int &i,ElemType e){
 //折半查找法 
 BubbleSort(L);
    int low=0,high=L.length-1,mid;     //置当前查找区间上、下界的初值
    while(low<=high)
    {
        if(L.elem[low]==e)
            i= low;
        if(L.elem[high]==e)
            i= high;          
        mid=low+((high-low)/2);
            /*使用(low+high)/2会有整数溢出的问题
            (问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,
              这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)
              不存在这个问题*/
        if(L.elem[mid]==e)
          i= mid;             //查找成功返回
        if(L.elem[mid]<e)
          low=mid+1;              
        else
          high=mid-1;             
    }
    if(low>high)
        return ERROR;//当low>high时表示所查找区间内没有结果,查找失败
}

Status QucikSort(Sqlist &L){
 int i, j,key;      /*定义变量为基本整型*/
    i = start;         /*将每组首个元素赋给i*/
    j = end;     /*将每组末尾元素赋给j*/
    key = L.elem[start];   /*设置基准值*/
    while (i < j)
    {
        while (i < j && key< L.elem[j])
            j--;    /*位置左移*/
        if (i < j)
        {
            L.elem[i] = L.elem[j];  /*将s[j]放到s[i]的位置上*/
            i++;     /*位置右移*/
        }
        while (i < j && L.elem[i] <= L.elem[0])
            i++;    /*位置右移*/
        if (i < j)
        {
            L.elem[j] = L.elem[i];  /*将大于基准值的s[j]放到s[i]位置*/
            j--;    /*位置右移*/
        }
    }
    L.elem[i] = key;    /*将基准值放入指定位置*/
    if (start < i)
        QucikSort(L, start, j - 1);/*对分割出的部分递归调用函数qusort()*/
    if (i < end)
       QucikSort(L, j + 1, end); 
}

main.cpp

#include "com_def.h"
#include "sqlist_def.h"
#include "sqlist_func.h"
using namespace std;
//1,6,8
int main(){
 Sqlist L;
 InitList_Sq(L); 
 //cout<<L.length<<endl; 
 int i,n;
 ElemType e;
 int choice=0;
 do{
  cout<<"***********************"<<endl;
  cout<<"* 1.插入元素          *\n";
  cout<<"* 2.删除元素          *\n";
  cout<<"* 3.输出元素          *\n";
  cout<<"* 4.按位置查找元素    *\n";
  cout<<"* 5.按值查找元素      *\n";
  cout<<"* 6.折半查找元素      *\n";
  cout<<"* 7.线性表冒泡排序    *\n";
  cout<<"* 8.线性表快速排序    *\n";
  cout<<"* 0.退出              *\n";
  cout<<"***********************"<<endl;
  cout<<"请输入你的选择:";
  cin>>choice;  
  switch(choice)
  {
   case 1:
    {
     cout<<"请输入插入位置和插入的数值"<<endl;
     cin>>i>>e;
     if(ListInsert_Sq(L,i,e)==OK)
     {
        cout<<"插入成功!"<<endl<<endl;
        Show(L);
     }
     else{
      cout<<"插入失败!"<<endl<<endl;
      Show(L);
     }
     break; 
    }
   case 2:
    {
     cout<<"请输入删除位置"<<endl;
     cin>>i;
     if(ListDelete_Sq(L, i, e))
     {
     cout<<"删除成功"<<endl;
     }
     else
     {
     cout<<"删除失败"<<endl;
     }
     cout<<"删除位置的值为"<<e<<endl;
     break;
    }
   case 3:
    {
     Show(L);
     break;
    }
   case 4:
    {
     cout<<"请输入查找的位置:";
     cin>>i;
     if(GetElem(L, i, e))
     {
      cout<<"查找成功!"<<endl;
      cout<<"查找位置的值为:"<<e<<endl;
     }
     else
     {
      cout<<"查找失败!"<<endl;
     }
     
     break; 
     } 
    case 5:
     {
      cout<<"请输入查找的值:";
     cin>>e;
     if(LocateElem(L, e))
     {
      cout<<"查找成功!"<<endl;
     }
     else
     {
      cout<<"查找失败!"<<endl;
     }
     cout<<"查找值的位置为:"<<i+1<<endl;
     break;
     }
   case 6:
    {
     cout<<"升幂排序"<<endl;
     BubbleSort(L);
     Show(L);
        cout<<"请输入查找数值:";
     cin>>e;
     if(!Binary_Search(L, i, e))
     {
     cout<<"查找成功"<<endl;
     }
     else
     {
     cout<<"查找失败"<<endl;
     }
     cout<<"查找数值的位置为:"<<i+1<<endl;
     break;
    }
   case 7:
    {
     cout<<"冒泡排序:"<<endl;
     BubbleSort(L);
     Show(L);
     break;
    }
   case 8:
    {
     cout<<"快速排序:"<<endl;
     QucikSort(L);
     Show(L);
     break;
    }             
  }//switch后 
 }while(choice!=0) ;
}

(2) 编程实现单链表的基本操作(建立、插入、删除、求表长、顺序查找、逆置、有序表的合并等),并设计一个菜单调用。

com_def.h

#include <stdio.h> 
#include <iostream>
#include <iomanip>
#include <string.h>
#include <malloc.h>
#include <process.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
typedef int Status;

linklist_def.h

typedef int ElemType;
typedef struct LNode{
 ElemType data;
 struct LNode *next;
}LNode,*LinkList;

linklist_func.h

#include "com_def.h"
using namespace std;
 /*初始化空表*/
Status Init_Linklist(LinkList &L)
{   
 int i,n;
 LinkList p,q;//p是指向第i个元素的指针 
    L=(LinkList)malloc(sizeof(LNode));
    if(!L) exit(OVERFLOW);
    L->next=NULL;// 空链表 
    q=L;//q为尾指针
 cout<<"利用尾插法开始建立链表!"<<endl; 
    cout<<endl<<"请输入元素的个数:";
 cin>>n;
 cout<<"输入 "<<n<<" 个元素:"<<endl; 
 for(i=1;i<=n;i++){
  p=(LinkList)malloc(sizeof(LNode));
  if(!p) exit(OVERFLOW);
  cin>>p->data;//元素的值存入链表 
  q->next=p;//下一个元素的地址赋给上一个元素的指针起到链接的作用 
  q=p;//再把p的地址赋给q 
 } 
 q->next=NULL;//创建链表完成 尾指针指空 
    return OK;
}
void OutputLinklist(LinkList &L){
 LinkList p;
 p=L->next;
 while(p){
  cout<<p->data;
  p=p->next;
 }
 cout<<endl; 
}
Status GetElem(LinkList &L,int i,ElemType &e){
 int j=1;
 LinkList p=L->next;
 while(p&&j<i)
 {
  p=p->next;
  j++;
 }
 if(!p||j>i) return ERROR;
 e=p->data;
 return OK;
}
Status Insert_Linklist(LinkList &L,int i,ElemType e){
 LinkList p,s;//s指向i-1个结点 
 int j=0;//j计数 
 p=L;//p为尾节点 
 while(p&&j<i-1)
 {
  p=p->next;
  ++j;//寻找第i-1个结点 
 }
 if(!p||j>i+1) return ERROR;
 s=(LinkList)malloc(sizeof(LNode));//生成新的结点 
 s->data=e;
 s->next=p->next;//插入L中 
 p->next=s;
 return OK;
}
Status ListDelete_L(LinkList &L,int i,ElemType &e){
 //在带头节点的单链线性表L中,删除第i个元素,并由e返回其值
 LinkList p,q;
 p=L;
 int j=0;
 while(p->next&&j<i-1)
 { //寻找第i个结点,并令p指向其前驱 
  p=p->next;
  ++j;
  } 
 if(!(p->next)||j>i-1) return ERROR;//删除位置不合理
 q=p->next;//q指向第i个结点 
 p->next=q->next;//令第i-1的结点直接与第i+1结点相连 
 e=q->data;
 free(q);
 return OK;  
}
void Length_Linklist(LinkList L){
 //求链表的长度 
 int num=0;
 LinkList p;
 p=L->next;
 while(p)
 {
  num++;
  p=p->next;
 }
 cout<<"链表的长度为:"<<num; 
}
void Inverse_Linklist(LinkList &L){
 LinkList p,q,r;
 if(!L->next||!L->next->next) return ;//链表为空,或者只有一个结点 
 p=NULL;//新建只有头结点的链表
 q=L->next;//指向当前需逆置链表的第一个结点 
 while(q)
 {
  r=q->next;//先保存下一个结点的位置 
  q->next=p;//存到新的链表
  p=q;   
  q=r;
  } 
 L->next=p;//把旧链表的头结点指向新的尾 
}
//void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){
// //已知单链线性表La和Lb的元素按值非递减排列
// //归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
// LinkList pa,pb,r;
// pa=La->next;
// pb=Lb->next;
// Lc=pc=La;
// while(pa&&pb){
//  if(pa->data<=pb->data){
//   pc->next=pa;
//   pc=pa;
//   pa=pa->next;
//  }
// } 
//}

void menu(){
  cout<<endl;
     cout<<"*********************************"<<endl;
  cout<<"* 1.创建单链表                  *\n";
  cout<<"* 2.显示单链表                  *\n";
  cout<<"* 3.查找元素                    *\n";
  cout<<"* 4.插入元素(尾插法)          *\n";
  cout<<"* 5.删除元素                    *\n";
  cout<<"* 6.单链表的长度                *\n";
  cout<<"* 7.逆置                        *\n";
  //cout<<"* 8.有序表的合并                *\n";
  cout<<"* 0.退出                        *\n";
  cout<<"*********************************"<<endl;
  cout<<endl;
}

main.h

#include "com_def.h"
#include "linklist_def.h"
#include "linklist_func.h"
#include "menu.h"
using namespace std;
int main(){
 LinkList L;
 int choice=0;
 int i,n;
 ElemType e; 
 do{
  menu();
  cout<<"请输入你的选择:";
  cin>>choice;  
  switch(choice)
  {
   case 1:
    {
     if(Init_Linklist(L))
     {
      cout<<"单链表创建成功\n";
                  cout<<"链表为:"<<endl;
                  OutputLinklist(L);
     }                 
              else
              {
               cout<<"单链表创建失败\n";
     }                 
              break;
    }
   case 2:
    {
     OutputLinklist(L);
     cout<<endl;
     break; 
    }
   case 3:
    {
     cout<<"请输入查找的位置:";
     cin>>i;
     if(GetElem(L, i, e))
     {
      cout<<"查找成功!"<<endl;
      cout<<"查找位置的值为:"<<e<<endl;
     }
     else
     {
      cout<<"查找失败!"<<endl;
     }     
     break;
    }
   case 4:
    {
     cout<<"请输入插入的位置:";
     cin>>i;
     cout<<"请输入插入的元素值:";
     cin>>e;
     if(Insert_Linklist(L, i, e))
     {
      cout<<"插入成功!\n";
                  cout<<"插入后的链表为:"<<endl;
                  OutputLinklist(L);
     }                
              else
              {
               cout<<"插入失败!\n";
     }                
              break;
    }
   case 5:
    {
     cout<<"请输入要删除的位置:";
     cin>>i;       
     if(ListDelete_L(L, i, e))
     {
      cout<<"删除成功!\n";
      cout<<"删除元素的值为:"<<e<<endl; 
                  cout<<"删除后的链表为:"<<endl;
                  OutputLinklist(L);
     }                 
              else
              {
               cout<<"删除失败!\n";
     }                
              break;
    }
   case 6:
    {
     Length_Linklist(L);
     cout<<endl;
     break; 
    }
   case 7:
    {
     cout<<"逆置后的链表为:"<<endl; 
     Inverse_Linklist(L);
     OutputLinklist(L);
     cout<<endl;
     break;
    }          
  }
 }while(choice!=0); 
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值