线性表之顺序表
一、顺序表概念
1.1 顺序表基本概念
线性表分为:顺序表、链表(单链表、双链表)
线性表的特征:对非空表,表头无前驱,表尾无后继,其他元素有且仅有一个直接前驱和一个直接后继。
顺序存储结构的表示:若将线性表L=(a0,a1, ……,an-1)中的各元素依次存储于计算机一片连续的存储空间。
顺序表缺点:1.对表的插入和删除等运算时间复杂度较差。2.要求系统提供一片较大的连续存储空间。
二、顺序表实现
2.0 格式
本文使用的是数组+动态内存分配的方式。
typedef struct
{
int data[10];
int last;
}sqlist,*sqlink;
2.1 文件结构
.
├── Makefile
├── sqlist.c
├── sqlist.h
└── test.c
2.2 编译步骤
2.2.1 老办法
2.2.1.1 多条命令
编译选项-c直接生成sqlist、test的.o文件该选项直接完成预处理、编译、汇编三个步骤
gcc -c sqlist.c -o sqlist.o
gcc -c test.c -o test.o
链接步骤
gcc sqlist.o test.o -o test
2.2.1.2 一步到位指令
gcc *.c -o test
2.2.2 使用Makefile
OBJS=sqlist.o test.o
CC=gcc
CLFAGS=-Wall -O -g
test:$(OBJS)
$(CC) $(OBJS) $(CLFAGS) -o test
clean:
rm *.o test
.PHONY:clean
2.3 头文件
typedef int data_t;
#define N 128
typedef struct sqlist_t
{
data_t data[N];
int last;
}sqlist, *sqlink;
sqlink list_create();//创建空的线性表
int list_clear(sqlink L);//清空线性表
int list_empty(sqlink L);//判断表是否为空
int list_length(sqlink L);//求线性表长度
int list_locate(sqlink L, data_t value);//定位value当前的位置
int list_insert(sqlink L, data_t value, int pos);//插入value当pos的位置
int list_show(sqlink L);//遍历线性表
int list_free(sqlink L);//释放动态内存
int list_delete(sqlink L, int pos);//删除某一节点(位置)
int list_merge(sqlink L1, sqlink L2);//合并两个线性表
int list_purge(sqlink L);//删除线性表中的重复元素
2.4 创建空的线性表
/*
创建一个结构体,这个结构体会开辟好一个128个int型元素的数组
和一个int型的计数元素
*/
sqlink list_create()
{
sqlink L;
L = (sqlink)malloc(sizeof(sqlist));
if(L == NULL)
{
printf("malloc error!\n");
return L;
}
memset(L, 0, sizeof(sqlist));
L->last = -1;
return L;
}
2.5 清空线性表
int list_clear(sqlink L)
{
/* 先判断表是否为空 */
if(L == NULL)
return -1;
memset(L, 0, sizeof(sqlist));
L->last = -1;
return 0;
}
2.6 判断表是否为空
int list_empty(sqlink L)
{
if(L->last == -1)
return 1;
else
return 0;
}
2.7 求线性表长度
/*
元素个数是从0开始的,所以数量应该+1
*/
int list_length(sqlink L)
{
if(L == NULL)
return 0;
return (L->last + 1);
}
2.8 定位value当前的位置
int list_locate(sqlink L, data_t value)
{
int i, iCount = 0;
/* 检查表是否为空 */
if(L == NULL)
return -1;
for(i = 0; i <= L->last; i++)
{
if(value == L->data[i])
{
return i;
}
}
return -1;
}
2.9 插入value当pos的位置
/*
pos是从0开始计数的
*/
int list_insert(sqlink L, data_t value, int pos)
{
int i;
/* 判断表是否满了 */
if(L->last == N - 1)
{
printf("list is full!\n");
return -1;
}
/* 参数是否合理 */
if(pos < 0 || pos > L->last + 1)
{
printf("pos is invalid!\n");
return -1;
}
/* 移动应该从后往前 */
for(i = L->last; i >= pos; i--)
{
L->data[i + 1] = L->data[i];
}
/* 存新值 */
L->data[pos] = value;
L->last++;
return 0;
}
2.10 遍历线性表
int list_show(sqlink L)
{
int i;
if(L==NULL || L->last == -1)
return -1;
for(i = 0; i <= L->last; i++)
{
printf("%d ", L->data[i]);
}
printf("\n");
return 0;
}
2.11 释放动态内存
int list_free(sqlink L)
{
if(L == NULL)
return -1;
free(L);
L = NULL;
return 0;
}
2.12 删除某一节点(位置)
/*
这里传进来的是pos位置
*/
int list_delete(sqlink L, int pos)
{
int i;
/* 判断位置是否合法或者空表 */
if(pos > L->last || L->last == -1)
{
printf("this pos is invalid!\n");
return -1;
}
/* 把这个位置之后的元素向前移动覆盖掉这个位置原来的数值 */
for(i = pos; i < L->last; i++)
{
L->data[i] = L->data[i + 1];
}
L->last--;
return 0;
}
2.13 合并两个线性表
/*
把第二个表先和第一个表对比,如果第一个表没有则插入第一个表中
*/
int list_merge(sqlink L1, sqlink L2)
{
int i = 0;
while(i <= L2->last)
{
if(list_locate(L1, L2->data[i]) == -1){
list_insert(L1, L2->data[i], L1->last+1);
}
i++;
}
return 0;
}
2.14 删除线性表中的重复元素
/*
原理:这个操作需要两个变量来定位i、j。i是用来遍历整个数组的。j是用来
和i位置的数值进行比较的。首先i从第二个位置开始遍历,i每取一个值出来就
需要让j从i-1的位置往前去做--操作来取对应位置的值来跟i位置的值进行比较。
比较分为两种情况,第一种情况:i位置和j位置的值不相等,j就继续--,直到
遇到相同的值或者--到第0个位置,后者的话j此时就会等于-1同时退出第二个
while循环回到第一个while循环,此时就要i++进行下一轮的比较;第二种情况,
i位置和j位置的值相等,此时要删除i位置的值调用list_delete函数,然后退出
第二个while循环,此时j还未到0,i应该再同一个的位置重新和i-1进行比较。
只有在j小于0也就是遍历完前i-1个数之后,i才可以++。
*/
int list_purge(sqlink L)
{
int i = 1, j;
if(L == NULL)
{
printf("list is empty!\n");
return -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;
}
2.15 测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlist.h"
int merge_list_test(){
sqlink L1, L2;
create_list_test(&L1);
create_list_test(&L2);
init_list_data(L1);
init_list_data(L2);
printf("merge before L1:");
list_show(L1);
list_insert(L2, 80, 0);
printf("L2:");
list_show(L2);
list_merge(L1, L2);
printf("merge after L1:");
list_show(L1);
list_free(L1);
list_free(L2);
return 0;
}
int delete_list_test(sqlink L){
list_delete(L, 0);
list_show(L);
return 0;
}
int postion_list_test(sqlink L){
int position = list_locate(L, 40);
printf("position is %d\n", position);
return 0;
}
int init_list_data(sqlink L){
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);
return 0;
}
int create_list_test(sqlink *L){
*L = list_create();
if(*L == NULL)
{
printf("list create failed!\n");
return -1;
}else
{
printf("list create success!\n");
}
return 0;
}
/*
位置都是从0开始的
*/
int main(int argc, char *argv[]){
sqlink L;
/* 想要改变L的内容就要传L的地址进去 */
create_list_test(&L);
init_list_data(L);
//postion_list_test(L);
//delete_list_test(L);
//merge_list_test();
list_free(L);
return 0;
}