欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第二章 线性表

程序员文章站 2022-03-10 19:55:20
...

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); 
}

第二章 线性表

相关标签: 数据结构