一、线性表简介:
1、线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列
2、线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储,但是把最后一个数据元素的尾指针指向了首位结点)
二、线性表的一般操作:
(1) InitList(& L)
//构造一个空的线性表
(2) DestroyList(& L)
//线性表存在了,消耗一个线性表
(3) ClearList(&L )
//清空线性表中的内容
(4) ListEmpty(L)
//判断线性表是否为空
(5) ListLength(L)
//返回线性表的长度
(6) GetElem(L,i,& e)
//返回线性表i位置上的元素值,通过e返回
(7) PriorElem(L,cur_e,&pre_e)
//若cur_e是线性表中的元素,且不是第一个,则返回该元素前一个元素的值
(8) NextElem(L,cur_e,&next_e)
//如果cur_e是线性表中的元素,而且不是最后一个,返回它下一个元素的值
(9) Listinsert(&L,i,e)
//如果线性表存在了,而且i符合条件,则在i位置插入一个元素
(10)ListDelete(&L,i)
//删除i位置上的元素
(11) ListDelete_data(&L,e,order)
//删除指定的元素e,order决定是删除一个,还是全部。
(12) Connect_two_List(L_a,L_b,& L_c)
//连接两个线性表,除去重复的内容
(13)print(L)
//打印线性表
三、线性表的合并与排序问题分析:
1、算法简介:
本文算法采用的是冒泡排序法,它的基本思想是比较相邻的两个数,如果前者比后者大,则进行交换。每一轮排序结束,选出一个未排序中最大的数放到数组后面,冒泡排序法是属于交换排序的,交换排序的基本思想都为通过比较两个数的大小,当满足某些条件时对它进行交换从而达到排序的目的
2、时间复杂度:
3、算法稳定性:
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不会再交换的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
四、附上合并排序的C语言源代码:
(附带保姆级注释,供初学者参考)
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
struct node{ //定义顺序表
int *elem;
int len;
};
void Init_arr(int len,struct node &arr) //1、初始化顺序表
{
int i=0,j=0,k=0; //2、定义i,j,k值均为0
int t;
arr.elem=(int *)malloc(len*sizeof(int));
//3、为该arr顺序表分配内存空间
if(arr.elem!=NULL)
//4、内存分配是否成功的判断
{
for(i=0;i<len;i++)
//5、进入for循环,当i不大于顺序表长度时,进行+1操作
scanf_s("%d",&arr.elem[i]);
//6、这里手动输入顺序表的元素(可无序)
arr.len=len;
//冒泡排序
for(j=0;j<len-1;j++)
//1、外层for循环表示arr中有len个数,比较次数为len-1
{
for(k=0;k<len-j-1;k++)
//2、内层for循环表示若第二个数比第一个数小进行两两交换的次数
{
if(arr.elem[k]>arr.elem[k+1])
//3、if判断前一个数大小是否大于后一个
{
t=arr.elem[k];
//4、若是,进行交换操作,其中t为交换的中间量
arr.elem[k]=arr.elem[k+1];
arr.elem[k+1]=t;
//5、完成位置交换
}
}
}
}
else{printf("内存分配失败!");
exit(0);
//6、else错误操作直接退出
}
}
void Combine_arr(struct node &arr1,struct node &arr2,struct node &arr) //归并顺序表,三个接口分别为表1,表2和合并完成的表
{
int i=0,j=0,k=0;
//1、创建第二个顺序表,步骤和第一个类似
arr.elem=(int *)malloc(1000*sizeof(int));
//2、为第二个顺序表申请空间
if (arr.elem!=NULL)
//3、若顺序表不空
{
while(i<arr1.len&&j<arr2.len)
//4、i表示第一个顺序表的下标,j表示第二个顺序表的下标
{
if(arr1.elem[i]>arr2.elem[j]){
//5、两两比较,若表1的i大于表2的j
arr.elem[k++]=arr2.elem[j];
//6、合并后的总表的第一个数就是第二个表中的j
j++;
//7、j执行加1操作继续与第一个表中的i进行比较
}
else{
arr.elem[k++]=arr1.elem[i];
//8、如果i为较小的那个,则合并后总表的第一个数为i
i++;
//9、执行i加1操作,继续与第二个表中的j进行比较
}
}
if(i>=arr1.len)
//10、只剩一个表还未归并入新表(即通过i++,数组下标已经达到了第一个表的最后一个,即第一个表最大元素小于第二个表的最小元素,此时第一个表全体入新表)
for(j;j<arr2.len;j++)
//11、此时只剩第二张表,进for循环
{
arr.elem[k++]=arr2.elem[j];
//12、下标为j的二表元素依次进入新表
}
else
{
for(i;i<arr1.len;i++)
//13、如果二表最大元素小于一表最小元素,即二表全部进入新表,一表没有元素进新表
arr.elem[k++]=arr1.elem[i];
//14、下标为i的一表元素进入新表
}
arr.len=k;
//15、新顺序表长度为最终的k
}
else
{
printf("内存分配失败!");
exit(0);
}
}
void traverse_arr(struct node &arr)
//1、遍历显示出顺序表
{
int i=0;
for(i=0;i<arr.len;i++)
//2、不超出范围的前提下,分别通过下标打印出新表元素
printf("%d ",arr.elem[i]);
printf("\n");
}
int main(void)
{
int p,q;
struct node arr1,arr2,arr;
printf("顺序表1的元素个数为:");scanf_s("%d",&p);
printf("请输入第1个顺序表元素:");Init_arr(p,arr1);
traverse_arr(arr1);
printf("顺序表2的元素个数为:");scanf_s("%d",&q);
printf("请输入第2个顺序表元素:");Init_arr(q,arr2);
traverse_arr(arr2);
Combine_arr(arr1,arr2,arr);
//对表一表二进行归并
traverse_arr(arr);
//再次遍历并输出总表
return 0;
}