【数据结构-C语言】线性表之顺序表(1)

线性表之顺序表

一、顺序表概念

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nebula嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值