线性表的基本运算
设线性表L=(a0,a1…,a(n-1)),对L的基本运算有:
(1)建立一个空表:list_create(L);
(2)置空表:list_clear(L);
(3)判断表是否为空:list_empty(L)。若表为空,返回值为1,否则返回0
(4)求表长:length(L)
(5)取表中某个元素:GetList(L, i),即ai。要求0<=i<=length(L)-1
(6)定位运算:Locate(L, x)。确定元素x在表L中的位置(序号)
(7)插入:
Insert(L,x,i)。将元素x插入到表L中第i个元素ai之前,且表长+1。
插入前: (a0,a1,—,ai-1,ai,ai+1-------,an-1) 0≤i≤n,i=n时,x插入表尾
插入后: (a0,a1,—,ai-1, x, ai,ai+1-------,an-1)
算法思路:若表存在空闲空间,且参数i满足:0≤i≤L->last+1,则可进行正常插入。
插入前,将表中(L->data[L->last]~L->data[i])部分顺序下移一个位置,然后将x插入L->data[i]处即可。算法对应的表结构。
(8)删除:Delete(L,i)。删除表L中第i个元素ai,且表长减1, 要求0≤i≤n-1。
删除前: (a0,a1,—,ai-1,ai,ai+1-------,an-1)
删除后: (a0,a1,—,ai-1,ai+1-------,an)
线性表的顺序存储缺点
线性表的顺序存储结构有存储密度高及能够随机存取等优点,但存在以下不足:
(1)要求系统提供一片较大的连续存储空间。
(2)插入、删除等运算耗时,且存在元素在存储器中成片移动的现象;
代码实现
sqlist.h
typedef int data_t; // typedef后面跟已有类型
#define N 128 // 后面跟的是宏
typedef struct {
data_t data[N];
int last;
}sqlist, *sqlink;
// 使用sqlink时,不需要加*,因为在typedef里面struct sqlist_t *是一体的,被sqlink所代替
sqlink list_create(); // 函数list_create的返回值是一个指针,指向结构体类型
int list_clear(sqlink L);
int list_delete(sqlink L);
int list_empty(sqlink L);
int list_length(sqlink L);
int list_locate(sqlink L, data_t value);
int list_insert(sqlink L, data_t value, int pos);
int list_show(sqlink L);
sqlist.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlist.h"
// 申请内存 初始化变量 返回指针
sqlink list_create() {
// 申请内存
sqlink L;
L =(sqlink)malloc(sizeof(sqlist)); // L接受的是所申请内存的起始地址,(sqlink)是强制类型转换,转换为结构体指针
if (L == NULL) {
printf("list malloc failed\n");
return L;
}
// 初始化变量
memset(L, 0, sizeof(sqlist)); // 从L开始的sizeof(sqlist)个字节全部用0填充
L->last = -1;
//return
return L;
}
/*
* @ret 0-success -1-failed
*/
int list_clear(sqlink L) { // 清除表的内容,表还在
if (L == NULL)
return -1;
memset(L, 0, sizeof(sqlist));
L->last = -1;
return 0;
}
int list_free(sqlink L){ // 表不在了
if (L == NULL)
return -1;
free(L);
L = NULL;
return 0;
}
/*
* list_empty: Is list empty?
* para L: list
* @ret 1--empty 0--not empty
* */
int list_empty(sqlink L) {
if (L->last == -1)
return 1;
else
return 0;
}
int list_length(sqlink L) {
if (L == NULL)
return -1;
return (L->last+1);
}
int list_locate(sqlink L, data_t value) {
return 0;
}
int list_insert(sqlink L, data_t value, int pos) {
int i;
//full,last是索引值,从0开始数
if (L->last == N-1) {
printf("list is full\n");
return -1;
}
//check para 0<=pos<=Last+1 [0, last+1],last+1表示往表末插入一个数
if (pos < 0 || pos > L->last+1) {
printf("Pos is invalid\n");
return -1;
}
//move,从后往前移,i=pos时,循环将pos对应的位置空了出来
for (i = L->last; i >= pos; i--) {
L->data[i+1] = L->data[i];
}
//update value last
L->data[pos] = value;
L->last++;
return 0;
}
int list_show(sqlink L) {
int i;
if (L == NULL)
return -1;
if (L->last == -1)
printf("list is empty\n");
for (i = 0; i <= L->last; i++) {
printf("%d ", L->data[i]);
}
puts(""); // puts默认加换行符,这里的作用就是换行
return 0;
}
test.c
#include <stdio.h>
#include "sqlist.h"
void test_insert();
int main(int argc, const char *argv[])
{
test_insert();
return 0;
}
void test_insert() {
sqlink L;
L = list_create();
if (L == NULL)
return;
list_insert(L, 10, 0);
list_insert(L, 20, 0);
list_insert(L, 30, 0);
list_insert(L, 40, 0);
list_insert(L, 50, 0);
list_insert(L, 60, 0);
list_show(L);
//list_insert(L, 100, list_length(L));
list_insert(L, 100, -1000);
list_show(L);
list_free(L);
}
线性表(顺序表)复杂操作的实现
删除
int list_delete(sqlink L, int pos) {
int i;
if (L->last == -1) {
printf("list is empty\n");
return -1;
}
//pos [0, last]
if (pos < 0 || pos > L->last) {
printf("delete pos is invalid\n");
return -1;
}
//move [pos+1, last] 删除后左移
for (i = pos+1; i <= L->last; i++) {
L->data[i-1] = L->data[i];
}
//update
L->last--;
return 0;
}
查找
/*
* @ret -1--not exist pos
* */
int list_locate(sqlink L, data_t value) {
int i ;
for (i = 0; i <= L->last; i++) {
if (L->data[i] == value)
return i;
}
return -1;
}
合并(并集)
// 依次取第二个表的元素,看看在表一中有没有,如果有,不做操作,若没有,插入进去
int list_merge(sqlink L1, sqlink L2) {
int i = 0;
int ret;
while (i <= L2->last){
ret = list_locate(L1, L2->data[i]);
if (ret == -1) {
if (list_insert(L1, L2->data[i], L1->last+1) == -1)
return -1;
}
i++;
}
return 0;
}
清除表中重复元素
// 从表的第二个位置(索引1的位置)开始向后遍历,每遍历到一个元素,就向前查找是否有重复元素,若有,删
// 除重复元素中相对靠后的那个,这样复杂度低一些
int list_purge(sqlink L) {
int i;
int j;
if (L->last == 0) // 最后一个元素的索引是0,说明只有一个元素
return 0;
i = 1; // 从索引1开始
while (i <= L->last) {
j = i-1;
while (j >= 0) {
if (L->data[i] == L->data[j]) {
list_delete(L, i);
break;
} else {
j--;
}
}
if ( j < 0) {
i++;
}
}
return 0;
}