数据结构学习笔记——顺序表的基本操作(超详细最终版+++)建议反复看看ヾ(≧▽≦*)o

简介: 数据结构学习笔记——顺序表的基本操作(超详细最终版+++)建议反复看看ヾ(≧▽≦*)o

前言


以下所有代码都经过测试,编译运行软件:Dev-C++ 5.11,若有表述和代码错误感谢指出!!!


一、顺序表的定义


以下操作均为顺序表的静态分配,所以其大小和空间是固定的,可通过MaxSize设置顺序表的最大长度。

#include<stdio.h>
#define MaxSize 10  //可自行更改最大长度
typedef struct {
  int data[MaxSize];  //元素
  int length;   //顺序表的当前长度
} SqList;  //顺序表的类型定义


二、顺序表的初始化


设置顺序表的初始长度为0,即L.length=0。

/*初始化顺序表*/
void InitList(SqList L) {
  L.length=0;
}


三、顺序表的建立


/*顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}


四、顺序表的输出


顺序表的输出,依次遍历从头到尾输出顺序表中各元素的值,即通过一个for循环,条件<L.length(顺序表的总长度),每次输出元素。

/*顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}


结合以上功能函数,如下,创建一个顺序表,长度为6,其功能是创建一个顺序表并输入元素,再通过函数调用依次输出各元素,数据元素依次为2,6,0,-1,4,8,如下完整代码:

#include<stdio.h>
#define MaxSize 10
typedef struct {
  int data[MaxSize];
  int length;
} SqList;
/*1、初始化顺序表*/
void InitList(SqList L) {
  L.length=0;
}
/*2、顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}
/*3、顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}
//主函数
int main() {
  SqList L;
  InitList(L);
  CreatList(L);
  printf("顺序表为:\n"); 
  DispList(L);
}


首先输入要创建顺序表中的元素个数,然后依次输入各数据元素,最后输出该顺序表,运行结果如下:

1667217572899.jpg


五、顺序表的逆序输出


顺序表的逆序输出也就是交换通过折半法,交换数据元素,然后也是通过调用DispList()函数依次遍历顺序表输出。

/*将顺序表中的所有元素逆置并输出*/
void ReverseList(SqList L) {
  int temp;
  for(int i=0; i<L.length/2; i++) {
  temp=L.data[i];
  L.data[i]=L.data[L.length-i-1];
  L.data[L.length-i-1]=temp;
  }
  DispList(L);  //调用输出函数
}


例如,接上一个例子,不过这次是逆序输出顺序表,如下完整代码:

/*将顺序表中的所有元素逆置并输出*/
void ReverseList(SqList L) {
  int temp;
  for(int i=0; i<L.length/2; i++) {
  temp=L.data[i];
  L.data[i]=L.data[L.length-i-1];
  L.data[L.length-i-1]=temp;
  }
  DispList(L);  //调用输出函数
}
/*2、顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}
/*3、顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}
/*4、将顺序表中的所有元素逆置并输出*/
void ReverseList(SqList L) {
  int temp;
  for(int i=0; i<L.length/2; i++) {
  temp=L.data[i];
  L.data[i]=L.data[L.length-i-1];
  L.data[L.length-i-1]=temp;
  }
  DispList(L);
}
//主函数
int main() {
  SqList L;
  InitList(L);
  CreatList(L);
  printf("逆序输出顺序表:\n");
  ReverseList(L);
}


运行结果如下:

1667217620479.jpg


六、顺序表的插入操作


顺序表的插入操作以位序进行插入元素,这里要注意位序是从1开始的,而c语言中的数组下标是从0开始的,这一点在插入操作中要明白,这里加了一个if语句判断输入的插入位置是否合法,若不合法则会返回false,插入后,要将其后的元素后移,最后数组长度加1。

/*顺序表的插入操作 (在L的位序i处插入元素e)*/
bool ListInsert(SqList &L,int i, int e) {
  if (i<1||i>L.length||L.length>=MaxSize)  //在[1,length+1]内有效且未存满或等于最大长度
  return false;  //插入失败返回 false
  for(int j=L.length; j>=i; j--)  //j变量等于顺序表的长度
  L.data[j]=L.data[j-1];  //将要插入的位置,第i个元素及以后的元素后移,先移动后面的元素,即数组下标小的赋给下标大的
  L.data[i-1]=e;    //由于数组的下标是从0开始的,所以位序要减一,即将要插入的元素e赋值给L.data[i-1]
  L.length++;  //数组长度加1
  return true;  //插入成功返回 true
}


例如,向之前所创建好的顺序表的位序为3(数组下标为2)处插入数据元素“7”,如下完整代码:

#include<stdio.h>
#define MaxSize 10
typedef struct {
  int data[MaxSize];
  int length;
} SqList;
/*1、初始化顺序表*/
void InitList(SqList L) {
  L.length=0;
}
/*2、顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}
/*3、顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}
/*4、顺序表的插入操作 (在L的位序i处插入元素e)*/
bool ListInsert(SqList &L,int i, int e) {
  if (i<1||i>L.length||L.length>=MaxSize)  //在[1,length+1]内有效且未存满或等于最大长度
  return false;  //插入失败返回 false
  for(int j=L.length; j>=i; j--)  //j变量等于顺序表的长度
  L.data[j]=L.data[j-1];  //将要插入的位置,第i个元素及以后的元素后移,先移动后面的元素,即数组下标小的赋给下标大的
  L.data[i-1]=e;    //由于数组的下标是从0开始的,所以位序要减一,即将要插入的元素e赋值给L.data[i-1]
  L.length++;  //数组长度加1
  return true;  //插入成功返回 true
}
//主函数
int main() {
  SqList L;
  InitList(L);
  CreatList(L);
  printf("当前顺序表为:\n");
  DispList(L);
  ListInsert(L,3,7);  //在顺序表L的位序为3处插入数据元素7
  printf("\n");
  printf("插入后的顺序表为:\n");
  DispList(L);
}


运行结果如下:

1667217677236.jpg


七、顺序表的删除操作


顺序表的删除操作同插入操作一样,也是通过位序插入/删除,删除目标元素后,其后的元素要向前移动一格,最后数组长度要减1。

/*顺序表的删除操作 (删除L中第i个位置的元素并引用变量e返回)*/
bool ListDelete(SqList &L,int i,int &e) {
  if (i<1||i>L.length)  //在[1,length+1]内有效
  return false; //删除失败返回true
  e=L.data[i-1];  //将要删除的元素赋值给e,由于是数组所以要i-1
  for(int j=i; j<L.length; j++)
  L.data[j-1]=L.data[j];  //将要删除的位置,第i个元素后的元素前移,先移动前面的元素,即下标大的赋值给下标小的
  L.length--;  //数组长度减1
  return true;  //删除成功返回true
}


例如对创建的顺序表,删除第4个元素(位序为4),然后输出顺序表,完整代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct {
  int data[MaxSize];
  int length;
} SqList;
/*1、初始化顺序表*/
void InitList(SqList L) {
  L.length=0;
}
/*2、顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}
/*3、顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}
/*4、顺序表的删除操作 (删除L中第i个位置的元素并引用变量e返回)*/
bool ListDelete(SqList &L,int i,int &e) {
  if (i<1||i>L.length)  //在[1,length+1]内有效
  return false; //删除失败返回true
  e=L.data[i-1];  //将要删除的元素赋值给e,由于是数组所以要i-1
  for(int j=i; j<L.length; j++)
  L.data[j-1]=L.data[j];  //将要删除的位置,第i个元素后的元素前移,先移动前面的元素,即下标大的赋值给下标小的
  L.length--;  //数组长度减1
  return true;  //删除成功返回true
}
//主函数
int main() {
  SqList L;
  int a;
  int e=0;  //初始化e的值 
  InitList(L);
  CreatList(L);
  printf("当前顺序表为:\n");
  DispList(L);
  printf("\n");
  printf("请输入想删除的元素位置:\n",a);
  scanf("%d",&a);
  if (ListDelete(L,a,e))
  printf("已删除顺序表中第%d个元素,其元素值为%d\n",a,e);
  else
  printf("输入的位序i不合法,删除操作失败!\n");
  printf("当前顺序表为:\n");
  DispList(L);
  return 0;
}


运行结果如下:

1667217718596.jpg


八、顺序表的按位和按值查找


顺序表的按位查找是以数组下标进行查找的,所以位序要减1,即L.data[i-1]。

/*顺序表的按位查找 (获取L中第i个位置元素的值)*/
int GetElem(SqList L,int i) {
  return L.data[i-1];  //立即找到第i个元素
}


顺序表的按值查找是,查找L中第一个元素值等于e的元素,它会依次沿着顺序表向后查找,找到后返回其位序。

/*顺序表的按值查找 (查找L中第一个元素值等于e的元素并返回其次序)*/
int LocateElem(SqList L,int e) {
  for(int i=0; i<L.length; i++)  //依次从前往后查找
  if(L.data[i]==e)
    return i+1; //数组下标为i的元素值为e,返回其位序i+1(数组从0开始)
  return 0; //未找到元素,退出循环查找失败
}


例如对创建的顺序表,查询顺序表中第3个位置的数据元素,另外查询顺序表中第一个元素值等于“4”的数据元素,其完整代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct {
  int data[MaxSize];
  int length;
} SqList;
/*1、初始化顺序表*/
void InitList(SqList L) {
  L.length=0;
}
/*2、顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}
/*3、顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}
/*4、顺序表的按位查找 (获取L中第i个位置元素的值)*/
int GetElem(SqList L,int i) {
  return L.data[i-1];  //立即找到第i个元素
}
/*5、顺序表的按值查找 (查找L中第一个元素值等于e的元素并返回其次序)*/
int LocateElem(SqList L,int e) {
  for(int i=0; i<L.length; i++)  //依次从前往后查找
  if(L.data[i]==e)
    return i+1; //数组下标为i的元素值为e,返回其位序i+1(数组从0开始)
  return 0; //未找到元素,退出循环查找失败
}
//主函数
int main() {
  SqList L;
  int a,b;
  InitList(L);
  CreatList(L);
  printf("顺序表为:\n");
  DispList(L);
  printf("\n");
  printf("按位查找第3个元素的值:\n");
  a=GetElem(L,3);
  printf("%d \n",a);
  printf("按值查找值为4的元素:\n");
  b=LocateElem(L,4);
  printf("%d \n",b);
}


运行结果如下:

1667217773705.jpg


基本操作的完整代码


以上顺序表基本操作的完整代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct {
  int data[MaxSize];
  int length;
} SqList;
/*1、初始化顺序表*/
void InitList(SqList L) {
  L.length=0;
}
/*2、顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}
/*3、顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}
/*4、将顺序表中的所有元素逆置并输出*/
void ReverseList(SqList L) {
  int temp;
  for(int i=0; i<L.length/2; i++) {
  temp=L.data[i];
  L.data[i]=L.data[L.length-i-1];
  L.data[L.length-i-1]=temp;
  }
  DispList(L);  //调用输出函数
}
/*5、顺序表的插入操作 (在L的位序i处插入元素e)*/
bool ListInsert(SqList &L,int i, int e) {
  if (i<1||i>L.length||L.length>=MaxSize)  //在[1,length+1]内有效且未存满或等于最大长度
  return false;  //插入失败返回 false
  for(int j=L.length; j>=i; j--)  //j变量等于顺序表的长度
  L.data[j]=L.data[j-1];  //将要插入的位置,第i个元素及以后的元素后移,先移动后面的元素,即数组下标小的赋给下标大的
  L.data[i-1]=e;    //由于数组的下标是从0开始的,所以位序要减一,即将要插入的元素e赋值给L.data[i-1]
  L.length++;  //数组长度加1
  return true;  //插入成功返回 true
}
/*6、顺序表的删除操作 (删除L中第i个位置的元素并引用变量e返回)*/
bool ListDelete(SqList &L,int i,int &e) {
  if (i<1||i>L.length)  //在[1,length+1]内有效
  return false; //删除失败返回true
  e=L.data[i-1];  //将要删除的元素赋值给e,由于是数组所以要i-1
  for(int j=i; j<L.length; j++)
  L.data[j-1]=L.data[j];  //将要删除的位置,第i个元素后的元素前移,先移动前面的元素,即下标大的赋值给下标小的
  L.length--;  //数组长度减1
  return true;  //删除成功返回true
}
/*7、顺序表的按位查找 (获取L中第i个位置元素的值)*/
int GetElem(SqList L,int i) {
  return L.data[i-1];  //立即找到第i个元素
}
/*8、顺序表的按值查找 (查找L中第一个元素值等于e的元素并返回其次序)*/
int LocateElem(SqList L,int e) {
  for(int i=0; i<L.length; i++)  //依次从前往后查找
  if(L.data[i]==e)
    return i+1; //数组下标为i的元素值为e,返回其位序i+1(数组从0开始)
  return 0; //未找到元素,退出循环查找失败
}


九*、顺序表删除的常用操作


删除顺序表中的最小值

删除顺序表中的所有特定值的元素

删除顺序表值在特定区间的元素

删除顺序表中重复元素

删除有序表中重复元素


具体的实现步骤感兴趣的小伙伴可以看之前这篇文章:

数据结构学习笔记:顺序表的删除操作及其演化题目总结


十*、顺序表的常用合并操作


顺序表的合并操作

若要将两个顺序表的数据元素合并,通过创建一个CombineList1()函数,将顺序表L1和顺序表L2分别添加至顺序表L3中,该函数中包含三个参数,分别是SqList L1,SqList L2,SqList &L3(顺序表L3由于被更改,所以要用引用符号),如下:

bool CombineList1(SqList L1,SqList L2,SqList &L3) {
...
}


只需设置一个while()循环,条件是该顺序表的长度,每次将该顺序表的值赋给最终顺序表,且每次循环变量都加1,如下:

while(i<L1.length)
  L3.data[k++]=L1.data[i++];
while(j<L2.length)
  L3.data[k++]=L2.data[j++];


该算法的完整代码:

/*合并两个顺序表*/
bool CombineList1(SqList L1,SqList L2,SqList &L3) {
  InitList(L3);
  int i=0,j=0;
  int k = 0;
  while(i<L1.length)
  L3.data[k++]=L1.data[i++];
  while(j<L2.length)
  L3.data[k++]=L2.data[j++];
  L3.length=k;
  return true;
}


例如,创建两个顺序表L1、L2,顺序表L1的数据元素依次为4、5、0、2、-1;顺序表L2的数据元素依次为8、1、4、7、2,将这两个顺序表合并为顺序表L3,并最后输出顺序表L3:

代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct {
  int data[MaxSize];
  int length;
} SqList;
/*1、初始化顺序表*/
void InitList(SqList L) {
  L.length=0;
}
/*2、顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}
/*3、顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}
/*4、合并两个顺序表*/
bool CombineList1(SqList L1,SqList L2,SqList &L3) {
  InitList(L3);
  int i=0,j=0;
  int k = 0;
  while(i<L1.length)
  L3.data[k++]=L1.data[i++];
  while(j<L2.length)
  L3.data[k++]=L2.data[j++];
  L3.length=k;
  return true;
}
//主函数
int main() {
  SqList L1,L2,L3;
  int a,b;
  InitList(L1);
  InitList(L2);
  InitList(L3);
  printf("建立第一个顺序表!\n");
  CreatList(L1);
  DispList(L1);
  printf("\n");
  printf("建立第二个顺序表!\n");
  CreatList(L2);
  DispList(L2);
  printf("\n");
  printf("合并后的顺序表如下:\n");
  CombineList1(L1,L2,L3);
  DispList(L3);
}


运行结果如下:

1667217890809.jpg


有序顺序表的合并操作

若要将两个有序顺序表的数据元素合并,我们则要对上述代码进行修改,即按顺序依次取两个顺序表较小的数据元素存入新的顺序表中,然后对剩余的数据元素再添加至新的顺序表的后面,创建一个函数CombineList2():

bool CombineList2(SqList L1,SqList L2,SqList &L3) {
...
}


该算法的完整代码如下:

/*5、合并有序顺序表*/
bool CombineList2(SqList L1,SqList L2,SqList &L3) {
  if(L1.length+L2.length>MaxSize)
  return false;
  int i=0,j=0;
  int k = 0;
  InitList(L3);
  while(i<L1.length&&j<L2.length) { //对两个顺序表中的元素两两比较,将小者存入结果表 
  if(L1.data[i]<=L2.data[j])
    L3.data[k++]=L1.data[i++];
  else
    L3.data[k++]=L2.data[j++];
  }
  while(i<L1.length)
  L3.data[k++]=L1.data[i++];
  while(j<L2.length)
  L3.data[k++]=L2.data[j++];
  L3.length=k;
  return true;
}


注:该代码参考《王道 数据结构 考研复习指导》

例如,创建两个有序顺序表L1、L2,有序顺序表L1的数据元素依次为-5、0、3、7;有序顺序表L2的数据元素依次为1、7、10,将这两个有序顺序表合并为有序顺序表L3,并最后输出有序顺序表L3:

代码如下:

#include<stdio.h>
#define MaxSize 10
typedef struct {
  int data[MaxSize];
  int length;
} SqList;
/*1、初始化顺序表*/
void InitList(SqList L) {
  L.length=0;
}
/*2、顺序表的建立*/
void CreatList(SqList &L) {
  printf("请输入建立顺序表的元素个数:\n");
  scanf("%d",&L.length);
  for(int i=0; i<L.length; i++) {
  int number=i+1;
  printf("请输入第%d个整数:\n",number);
  scanf("%d",&L.data[i]);
  }
}
/*3、顺序表的输出(从头到尾输出顺序表中各元素的值)*/
void DispList(SqList L) {
  for(int i=0; i<L.length; i++)
  printf("%d ",L.data[i]);
}
/*4、合并有序顺序表*/
bool CombineList2(SqList L1,SqList L2,SqList &L3) {
  if(L1.length+L2.length>MaxSize)
  return false;
  int i=0,j=0;
  int k = 0;
  InitList(L3);
  while(i<L1.length&&j<L2.length) { //对两个顺序表中的元素两两比较,将小者存入结果表 
  if(L1.data[i]<=L2.data[j])
    L3.data[k++]=L1.data[i++];
  else
    L3.data[k++]=L2.data[j++];
  }
  while(i<L1.length)
  L3.data[k++]=L1.data[i++];
  while(j<L2.length)
  L3.data[k++]=L2.data[j++];
  L3.length=k;
  return true;
}
//主函数
int main() {
  SqList L1,L2,L3;
  int a,b;
  InitList(L1);
  InitList(L2);
  InitList(L3);
  printf("建立第一个有序顺序表!\n");
  CreatList(L1);
  DispList(L1);
  printf("\n");
  printf("建立第二个有序顺序表!\n");
  CreatList(L2);
  DispList(L2);
  printf("\n");
  printf("合并后的有序顺序表如下:\n");
  CombineList2(L1,L2,L3);
  DispList(L3);
}


运行结果如下:

1667217963490.jpg

后续更新分割线……

1667217973888.jpg

相关文章
|
5天前
|
存储
数据结构链表详解(不仅顺序表可以,我链表也可以)
数据结构链表详解(不仅顺序表可以,我链表也可以)
12 0
|
1天前
|
存储 算法
数据结构与算法③(第二章上)顺序表的实现(动态顺序表+菜单)
数据结构与算法③(第二章上)顺序表的实现(动态顺序表+菜单)
3 0
|
1天前
|
存储 算法
数据结构——复杂度和顺序表
数据结构——复杂度和顺序表
6 0
|
5天前
|
C语言
顺序表的实现(迈入数据结构的大门)(2)
顺序表的实现(迈入数据结构的大门)(2)
7 0
|
5天前
顺序表的实现(迈入数据结构的大门)(1)
顺序表的实现(迈入数据结构的大门)(1)
7 0
|
6天前
|
C++
数据结构(顺序表 动态定义
数据结构(顺序表 动态定义
12 2
|
6天前
|
C++
数据结构(顺序表
数据结构(顺序表
13 1
|
6天前
|
存储
【栈】基于顺序表的栈功能实现
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
14 0
|
6天前
|
存储 编译器
【数据结构】~顺序表
【数据结构】~顺序表
|
6天前
|
存储
数据结构第二课 -----线性表之顺序表
数据结构第二课 -----线性表之顺序表