C语言高级-2线性表-顺序表

目录

一、线性表定义、特点

二、顺序存储结构

三、线性表的基本运算

1、设线性表 L=(a0,a1, ……,an-1),对 L的基本运算有:

2、算法实现

(1)建立一个空表:sqlink list_create()。

(2)置空表:data_t list_clear(sqlink L)

(3)判断表是否为空:data_t list_empty (sqlink L)。

(4)求表长:data_t length (sqlink L)

(5)取表中某个元素的下标:data_t list_locate(sqlink L,data_t value)

(6)取表中某个元素的值:data_t list_getlist(sqlink L,int i)

(7)插入:data_t list_insert(sqlink L,data_t value,int i)。

(8)删除:int list_delete(sqlink L,int i)。

(9)释放内存:int list_free(sqlink L)

(10)打印:int list_show(sqlink L)。

(11)线性表去重 :int list_purge(sqlink L)

(12)线性表合并 :int list_merge(sqlink L1,sqlink L2)

实现创建test.c调用接口

创建makefile方便编译

总结:


一、线性表定义、特点

1、定义:线性表是包含若干数据元素的一个线性序列记为:

L=(a0, ...... ai-1, ai, ai+1 ...... an-1)L为表名

ai (0≤i≤n-1)为数据元素;

n为表长,n>0 时,线性表L为非空表,否则为空表。

线性表:L可用二元组形式描述:

L=(D,R)

即线性表L包含数据元素集合D和关系集合R

D={ai | ai ∈datatype, i = 0,1,2 -----n-1,n≥0}

R={<ai , ai+1> | ai , ai+1 ∈D,0≤i≤n-2}

  • 关系符<ai,ai+1>在这里称为有序对
  • 表示任意相邻的两个元素之间的一种先后次序关系
  • ai是ai+1的直接前驱,ai+1是ai的直接后继

例如:

设有一个顺序表L={1,2,3,4,5,6};他们的关系如图:

①-②-③-④-⑤-⑥

使用二元组描述L=(D,R),则

        D = {1,2,3,4,5,6}{n=6}

        R = {<1,2>,<2,3>,<3,4>,<4,5>,<5,6>}

2、特点:

  • 对非空表,a0是表头,无前驱;
  • an-1是表尾,无后继;
  • 其它的每个元素ai有且仅有一个直接前驱ai-1和一个直接后继ai+1。

二、顺序存储结构

若将线性表L=(a0,a1,.....an-1)中各元素依次存储于计算机一片连续的存储空间。

设Loc(ai)为ai的地址,Loc(a0),每个元素占d个单元则:

Loc(ai)= b+i*d

b:a0
b+d:a1
b+i*d:ai

...

...        
b+(n-1)*d:an-1

1、顺序存储结构的特点
(1)逻辑上相邻的元素 ai, ai+1,其存储位置也是相邻的。对数据元素ai的存取为随机存取或按地址存取存储密度高存储密度D=(数据结构中元素所占存储空间)/(整个数据结构所占空间)

(2)顺序存储结构的不足:对表的插入和删除等运算的时间复杂度较差。适合查找对,插入删除少的情况

2、存储结构

在C语言中,可借助于一维数组类型来描述线性表的顺序存储结构

#define N 100       
typedef int data_t;
typedef struct                    
{   
    data_t data[N]; //表的存储空间     
    int last;        //存放数组最后一个元素的下标
}sqlist,*sqlink;
a0
...
ai
..,
last

三、线性表的基本运算

1、设线性表 L=(a0,a1, ……,an-1),对 L的基本运算有:

(1)建立一个空表

(2)置空表:

(3)判断表是否为空

(4)求表长

(5)取表中某个元素

(6)定位运算,确定元素x在表L中的位置(或序号)       

(7)插入

(8)删除:list_delete(L,i)。删除表L中第i个元素ai,且表长减1, 要求0≤i≤n-1

(9)释放表内存

(10)表打印

(12)线性表去重 

(13)线性表合并 

2、算法实现

思路:一般编程会写4个文件

  • sqlist.h   //数据结构定义,运算
  • sqlist.c   // 运算的实现
  • test.c      //根据应用提供接口
  • makefile  //因为gcc 编译每次需要敲很多命令,通过make可以更便捷,需要了解可参考

-------------->makefile管理工具

这样布局的好处:

  • 结构清晰
  • 软件复用(给自己用,给同事,外包,包括.h和.o文件,源码自己保留)


sqlist.h文件展示

#define N 100

typedef int data_t;

typedef struct{
	data_t data[N];
	int last;
}sqlist, *sqlink;

sqlink list_create();
int list_clear(sqlink L);
int list_isempty(sqlink L);
int list_length(sqlink L);
int list_locate(sqlink L,data_t value);
data_t list_getlist(sqlink L,int i);
int list_insert(sqlink L,data_t value,int i);
int list_delete(sqlink L,int i);
int list_free(sqlink L);
int list_show(sqlink L);
int list_purge(sqlink L);
int list_merge(sqlink L1,sqlink L2);

(1)建立一个空表:sqlink list_create()。

函数类型:指针函数,若需要其他数据结构,方便用户通过指针切换。

参数:无

返回值:指针

描述:首先创建一个结构体指针,对指针分配内存空间(malloc),若分配成功,对数组清零操作(memset),下标last=-1代表空。

#include<stdio.h>
#include "sqlist.h"
#include <stdlib.h>
#include <string.h>

sqlink list_create(){                                            
                                                                 
        sqlink L;                                                
        L = (sqlink)malloc(sizeof(sqlist));                      
        if( L  == NULL)                                          
        {                                                        
                printf("sqlist malloc failed\n");                
                return L;                                        
        }                                                        
        L = memset(L,0,sizeof(sqlist));                          
        L->last = -1;                                            
        printf("sqlist is create\n");                            
        return L;                                                
}     

(2)置空表:data_t list_clear(sqlink L)

函数类型:int型

参数:指针

返回值:置空成功返回0,输入函数为空返回-1

描述:判断输入函数是否为空,不为空清0数组,下标last置-1。

int list_clear(sqlink L){

//empty
        if(L == NULL)
        {
                printf("list is empty\n");
                return -1;
        }
//clear
	L = memset(L,0,sizeof(sqlist));	
        L->last = -1;

        return 0;
}

(3)判断表是否为空:data_t list_empty (sqlink L)。

函数类型:int型

参数:指针

返回值:若表为空,返回值为1 , 否则返回 0

描述:判下标last是否为-1。

int list_isempty(sqlink L){
	
//empty
        if(L->last == -1)
        {
                printf("list is empty\n");
		return 1;
	}
	printf("list is not empty\n");
	return 0;	
}

(4)求表长:data_t length (sqlink L)

函数类型:int型

参数:指针

返回值:表长度

描述:不为空,返回下标last+1。数组是从0开始,所以要加1。

int list_length(sqlink L){
	if( L == NULL){
		printf("list is NULL\n");
		return -1;
	}
	return L->last+1;
}

(5)取表中某个元素的下标:data_t list_locate(sqlink L,data_t value)

函数类型:int型

参数1:指针

参数2:数据值

返回值:找到返回下标,没找到返回-1

描述:遍历是否等于value,找到返回

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;
}

(6)取表中某个元素的值:data_t list_getlist(sqlink L,int i)

函数类型:data_t

参数1:指针

参数2:下标

返回值:找到数据,没找到返回-1

描述:取数组的值,增加了参数检查判断。

data_t list_getlist(sqlink L,int i){
  	if (L == NULL){
		return -1;
	}
  	if (L->last == -1)
		printf("list is empty");
		return -1;
	if(i<0 || i>L->last){
		printf("out of range\n");
		return -1;
	}
	return L->data[i];
}

(7)插入:data_t list_insert(sqlink L,data_t value,int i)。

函数类型:int型

参数1:指针

参数2:数据值

参数3:位置

返回值:成功返回0,失败返回-1

描述:把ch[i]到ch[last]的数据整体移动到ch[i+1]到ch[last+1]的位置,再赋值ch[i] =value。要求表长+1。

data_t list_insert(sqlink L,data_t value,int i){
	int j;
	
//full
	if(L->last == N-1)
	{
		printf("list is full\n");
		return -1;
	}

//check para [0,last+1]
	if( i < 0 || i > L->last + 1){
		printf("i is  out of range\n");
		return -1;
	}
//move [i,last+1]
	for(j = L->last; j >= i; j--){
	 
		L->data[j+1] = L->data[j];
	}
	L->data[i] = value;
	L->last++;
	printf("Last:%d ",L->last);
	return 0;
}

(8)删除:int list_delete(sqlink L,int i)。

函数类型:int型

参数1:指针

参数2:位置 (范围校验)

返回值:成功返回0,失败返回-1

描述:删除表L中第i个元素。把ch[i+1]到ch[last]的数据整体移动到ch[i]到ch[last-1]的位置。要求表长-1。

int list_delete(sqlink L,int i){
	int j;

//empty
        if(L->last == -1)
        {
                printf("list is empty\n");
                return -1;
        }

//check para [0,last]
        if( i < 0 || i > L->last){
                printf("i is  out of range\n");
                return -1;
        }

//move [i+1,last)
        for(j = i+1 ; j <= L->last; j++){

                L->data[j-1] = L->data[j];
        }
        L->last --;

	return 0;
}

(9)释放内存:int list_free(sqlink L)

int list_free(sqlink L){
	if(L==NULL)
		return -1;
	free(L);
	L=NULL;
	return 0;
}

(10)打印:int list_show(sqlink L)。

函数类型:int型

参数1:指针

返回值:成功返回0,失败返回-1

描述:遍历数组

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("");
	return 0;
}

(11)线性表去重 :int list_purge(sqlink L)

函数类型:int型

参数1:指针

返回值:成功返回0,失败返回-1

描述:定义两个下标i和j,i指向1,j指向i-1。循环判断i之前的数据是否与i相同,若相同删除数据,若不相同,i++。

int list_purge(sqlink L){
	int i=1,j;
//empty
	if(list_isempty(L)){
		return -1;
	}	
//only onei
	if(L->last ==0)
		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++;
	}
	list_show(L);
	return 0;
}

(12)线性表合并 :int list_merge(sqlink L1,sqlink L2)

函数类型:int型

参数1:表1指针

参数2:表2指针

返回值:成功返回0,失败返回-1

描述:遍历表2的值,逐个插入到表1尾部。

int list_merge(sqlink L1,sqlink L2){
//check
	if(L1 == NULL || L2 == NULL){
		return -1;
	}
	if(L1->last+1+L2->last+1 >N){
		printf("full\n");
		return -1;
	}
	
	int i = 0;
	while(i <= L2->last){
		if(list_locate(L1,L2->data[i]) == -1){   //判断是否重复数据
			if(list_insert(L1,L2->data[i],L1->last+1) == -1)
				return -1;
		}
		i++;
	}
	list_free(L2);
	return 0;
}

实现创建test.c调用接口

#include<stdio.h>
#include "sqlist.h"

int main(char argc,char *argv[]){

	sqlink L;
//create
	L = list_create();	

//insert	
	list_insert(L,1,0);	
	list_insert(L,1,0);	
	list_insert(L,2,0);
	list_insert(L,2,0);
	list_insert(L,4,0);
	list_insert(L,5,0);
//lengh
	printf("length:%d\n",list_length(L));
	list_insert(L,6,list_length(L));
//show
	list_show(L);
//delete
	list_delete(L,0);
	list_show(L);
//getlist
	list_getlist(L,5);
//purge
	list_purge(L);
//merge
	sqlink L2;
	L2 = list_create();
	list_insert(L,10,0);	
	list_insert(L,11,1);	
	list_insert(L,12,2);	
	list_insert(L,13,3);	
	list_show(L2);
	list_merge(L,L2);
	list_show(L);
	return 0;
}



创建makefile方便编译

OBJS= sqlist.o test.o
CC= gcc
CFLAGS= -c

test:test.o sqlist.o

.PYONY:clean
clean:
	rm *.o test

总结:

线性表的顺序存储结构有存储密度高及能够随机存取等优点,但存在以下不足:

  • 要求系统提供一片较大的连续存储空间。
  • 插入、删除等运算耗时,且存在元素在存储器中成片移动的现象。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

4IOT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值