目录
一、线性结构
二、线性表
三、顺序表
顺序表实现-静态数组
顺序表实现-动态数组
练习题
1.合并数组
2.划分问题
3.连续插入
4.连续删除
定义:结构是非空有限集,有且仅有一个开始节点和结束节点,所有节点最多只有一个直接前驱和直接后继。节点间逻辑关系:(1:1)
线性结构的逻辑类型:包括线性表、堆栈、队列、字符串、数组等。最典型、最常用的是线性表。(线性结构不是线性表)
定义:有限数据元素形成的序列
特点:数据元素都为同类型。元素间关系为线性。
线性表的物理结构类型:顺序存储结构和链式存储结构
ps:有序表:所有元素以递增或递减方式有序排列的线性表。有序表是线性表的一部分。有序表(数值上有序)不等于顺序表(物理上有序)。
顺序存储特点:
优点:可以随机存取表中任一元素,方便快捷
缺点:在插入或删除某一元素时,需要移动大量元素
顺序表元素地址计算:LOC(ai) = 首地址 + 每个元素的存储空间 *(i - 1)
顺序表在C语言中用一维数组来描述。
操作:
名称 | 修改 | 插入 | 删除 |
目的 | 修改第pos个元素的值 | 在线性表第pos个位置前插入一个元素 | 删除线性表的第pos个位置上的元素 |
步骤 | l.elem[pos-1]=value | 将第n至第pos位的元素向后移动一个位置; 将要插入的元素写到第pos个位置; 表长加1。 |
将第pos+1至第n 位的元素向前移动一个位置; 表长减1。 |
时间复杂度 | O(1) | 平均时间复杂度O(n) | 平均时间复杂度O(n) |
注意 | pos都是从1开始算的 | 判断pos值是否合法,表是否已满 | 判断pos是否合法,表是否为空 插入删除的平均空间复杂度为O(1) |
代码:
说明:
//线性表的静态顺序存储(数组)
#include
#include
#define MAXSIZE 20 //最多放置数据个数
typedef int elemtype; //数据类型
typedef struct {
elemtype elem[MAXSIZE];
int length;
}list;
void insert(list& l, int pos, elemtype value) //在第pos个元素前插入元素
{
int i;
if (l.length == MAXSIZE)
{
printf("full!");
return;
}
if (pos<1 || l.length + 1= pos - 1; i--)
l.elem[i + 1] = l.elem[i];
l.elem[pos - 1] = value;
l.length++;
}
elemtype delet(list& l, int pos, elemtype& e)//删除第i个元素,e返回其值
{
int i;
if (l.length == 0 || pos<1 || pos>l.length)
{
printf("wrong!");
return NULL;
}
e = l.elem[pos - 1];
if (pos < l.length) //如果不是删除最后值,pos及以后元素前移
for (i = pos; i < l.length; i++)
l.elem[i - 1] = l.elem[i];
l.length--;
return e;
}
void changeelem(list& l, int pos, elemtype value) //改变元素值
{
l.elem[pos - 1] = value;
}
void output(list L) //打印线性表中所有元素
{
printf("当前顺序表的长度为: %d\n", L.length);
for (int i = 0; i < L.length; i++) {
printf("%d ", L.elem[i]);
}
printf("\n");
}
int main() {
list l;
l.length = 0;
for (int i = 1; i <= 10; i++) {
insert(l, i, i);
}
output(l);
insert(l, 3, 99);
output(l);
elemtype e;
delet(l, 6, e);
output(l);
printf("%d\n", e);
e = 99;
changeelem(l, 7, e);
output(l);
}
操作:
名称 | 初始化 | 插入 | 删除 | 定位 |
目的 | 为数组开辟空间 | 在第pos个元素之前插入一个值为value的元素 | 将第pos个位置上的元素删除 | 根据值找到元素的位置 |
步骤 | 申请空间,确定当前表的元素数和存储容量 | 检测位置是否合法、空间是否足够,不够新增空间、修正存储容量; 元素后移,插入新元素; 修正表长。 |
检测位置是否合法,元素前移,修正表长 | 逐个比较,返回下标 |
采用realloc(p,newsize)扩大空间 注意:newsize是空间的大小,是数据个数*sizeof(数据类型) |
时间复杂度 O( ListLength(L) ) |
代码:
#include
#include
#define list_size 3 //最多放置数据个数
#define increment_size 5 //补充空间
typedef int elemtype;
typedef struct {
elemtype* elem;
int length;
int listsize;
}list;
void initlist(list& l) { //构造一个新的线性表
l.elem = (elemtype*)malloc(list_size * sizeof(elemtype));
if (!l.elem)
{
printf("wrong!");
return;
}
l.length = 0;
l.listsize = list_size;
}
void insert(list& l, int pos, elemtype value) //在第pos个元素前插入元素。注意,长度和pos都是从1开始数,而表从0开始编号
{
int i;
if (l.length == list_size) {
l.elem = (elemtype*)realloc(l.elem, (list_size + increment_size) * sizeof(int)); //realloc(原指针,需要的长度)
l.listsize += increment_size;
}
if (pos<1 || pos>l.length + 1)
{
printf("worng number!");
return;
}
if (pos <= l.length) {
for (i = l.length - 1; i >= pos - 1; i--) {
l.elem[i + 1] = l.elem[i];
}
}
l.elem[pos - 1] = value;
l.length++;
}
void delet(list& l, int pos)//删除第i个元素
{
int i;
if (l.length == 0 || pos<1 || pos>l.length)
{
printf("worng number!\n");
return;
}
printf("\n删除第%d个元素\n",pos);
if (pos < l.length)
for (i = pos; i < l.length; i++)
l.elem[i - 1] = l.elem[i];
l.length--;
}
int locateelem(list l, elemtype value, int& e) //找到特定值的位置
{
if (l.length == 0)
{
printf("worng number!");
return 0;
}
for (e = 0; e < l.length; e++)
if (l.elem[e] == value)
break;
if (e < l.length)
{
printf("\n值为%d的元素为第%d个\n", value, e + 1);
return ++e;
}
else {
printf("not found");
return 0;
}
}
void output(list L) //打印线性表
{
printf("当前顺序表的长度为: %d\n", L.length);
for (int i = 0; i < L.length; i++) {
printf("%d ", L.elem[i]);
}
printf("\n");
}
int main() {
list l;
initlist(l);
output(l);
int i = 0;
for (i = 1; i <= list_size; i++)
insert(l, i, i);
output(l);
insert(l, 3, 99);
output(l);
delet(l, 2);
output(l);
int e;
locateelem(l, 99, e);
}
有两个有序的顺序表LA(有m个元素)和LB(有n个元素)其元素均以从小到大的升序排列,编写一个函数将它们合并成一个顺序表LC,并要求LC仍保持其有序性。
#include
#include
#define elemtype int
typedef struct {
elemtype* elem;
int length;
}list;
void initlist(list& l, int num) //构造一个新的线性表
{
l.elem = (elemtype*)malloc(num * sizeof(elemtype));
if (!l.elem)
{
printf("wrong!");
return;
}
l.length = 0;
}
void insert(list& l, int pos, elemtype value)
{
int i;
if (pos<1 || pos>l.length + 1)
{
printf("worng number!");
return;
}
if (pos <= l.length) {
for (i = l.length - 1; i >= pos - 1; i--) {
l.elem[i + 1] = l.elem[i];
}
}
l.elem[pos - 1] = value;
l.length++;
}
void output(list L) //打印线性表
{
for (int i = 0; i < L.length; i++) {
printf("%d ", L.elem[i]);
}
printf("\n");
}
void function(list la, list lb, list lc)
{
int a = 0, b = 0, c = 0;
while (a < la.length && b < lb.length)
{
if (la.elem[a] <= lb.elem[b])
lc.elem[c++] = la.elem[a++];
else
lc.elem[c++] = lb.elem[b++];
}
if (a = la.length)
while(b < lb.length)
lc.elem[c++] = lb.elem[b++];
if (b = lb.length)
while (a < la.length)
lc.elem[c++] = la.elem[a++];
printf("LC为:");
for (int i = 0; i < la.length + lb.length; i++)
printf("%d ", lc.elem[i]);
}
int main() {
int i, temp, numa, numb;
list la,lb,lc;
printf("la长度:");
scanf_s("%d", &numa);
initlist(la, numa);
printf("输入元素,空格间隔:");
for (i = 1; i <= numa; i++) {
scanf_s("%d", &temp);
insert(la, i, temp);
}
printf("lb长度:");
scanf_s("%d", &numb);
initlist(lb, numb);
printf("输入元素,空格间隔:");
for (i = 1; i <= numb; i++) {
scanf_s("%d", &temp);
insert(lb, i, temp);
}
printf("LA为:");
output(la);
printf("LB为:");
output(lb);
initlist(lc, numa+numb);
function(la, lb, lc);
}
将动态顺序表 (a1,a2,... ,an) 重新排列为以 a1 为界的两部分:a1 前面的值均比 a1小,a1 后面的值都比 a1 大。这一操作称为划分。a1称为基准。
采用了快速排序思想:指针pl、pr分别指向数组两端。pr先向左移动,找到比基准小的值赋给pl,pl再向右移动,找到比基准大的值赋给pr,直到两指针相遇,将基准放在相遇处。
//采用一趟快速排序思想,以a1作为枢轴元素,分别从高到低和从低到高扫描元素
#include
#include
void function(int*& l, int num)
{
int target = l[0];
int pl = 0, pr = num - 1;
while (pl < pr)
{
while (pl < pr && l[pr] > target)
pr--;
if (pl < pr)
l[pl++] = l[pr];
while (pl < pr && l[pl] < target)
pl++;
if (pl < pr)
l[pr--] = l[pl];
}
l[pl] = target;
}
int main() {
int num, i;
printf("元素个数:");
scanf_s("%d", &num);
int* l = (int*)malloc(num * sizeof(int));
if (!l) return 0;
printf("输入内容:");
for (i = 0; i < num; i++)
scanf_s("%d", &l[i]);
function(l, num);
printf("更新后: ");
for (i = 0; i < num; i++)
printf("%d ", l[i]);
}
在具有n个元素的动态顺序表中第i个位置之后插入m个元素
用realloc扩大空间,后移旧元素,放入新元素
大二上学期学习数据结构,这是一段艰辛但收获颇丰的旅程。期末临近,特将日常笔记及代码整理成文,当作复习,也希望能给各位计算机学习者提供帮助。如有错误,请留言指正。2023.12.5