数据结构——线性表学习总结1(顺序表)

前言:我是为了考研来学习的数据结构,作为计算机专业基础课,它是当值无愧的一块难啃的硬骨头,对于我这个跨专业的考生学起来非常的难受;前面发的C学习的博客是为了学习这里的铺垫,毕竟不熟悉结构体、指针、还有malloc()等函数简直就不是到那些代码写的啥。下面的总结笔记主要来自于小甲鱼老师的视频教程,我边看边暂停记笔记写代码,在博客里做一个归拢,当作一个回顾和复习(其实和预习差不多)。

一、线性表定义及特点
1、定义

  • 一个线性表是由零个或多个元素组成的有限序列;

2、特点

  • 是一个非空的有限集
  • 若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其余元素有且仅有一个前驱和后继;

3、记法

  • Date 记作(a1,a2,a3,…ai,a(i+1),…an);
  • n为线性表长度;
  • n = 0为空表;

二、线性表作为抽象数据类型所定义的一些操作

1、什么是抽象数据类型

  • 抽象数据类型(Abstract Date Type,ADT):是指一个数学模型以及定义在此数学模型上的一组操作;
  • 描述方法:可用(D,S,P)三元组表示:
    |D| 数据对象 |
    |S|D上的关系集|
    |P | 对D的基本操作集 |

2、线性表常用的基本操作总览

  • InitList(*L):初始化操作,构建一个空的线性表;
  • ListEmpty(L):判断线性表是否为空,若为空则返回TRUE,否则返回FALSE;
  • ClearList(*L):清空线性表;
  • GetElem(L,i,*e):将线性表L中的第i个位置元素返回给e;
  • LocateElem(L,e):在线性表中查找与e相等的元素,成功返回i,无返回0;
  • ListInsert(*L,i,e):在线性表L中第i个位置插入新元素e;
  • ListDelete(*L,i,*e):删除线性表L中第i个元素,并用e返回其值;
  • ListLength(L):返回线性表L的元素个数;

三、基本操作的结构代码及其算法思路

1、线性表顺序存储结构(顺序表)的结构代码

#define MAXSIZE 20
typedef int ElemType;
typedef struct{
	ELemType date[MAXSIZE];
	int length;   //线性表当前长度
}SqList;
//实际上是对数组封装,增加了当前长度变量length

顺序存储结构封装需三个属性:

  • 存储空间的起始位置,即数组date的存贮位置date[0];
  • 最大存储容量,即数组长度MAXSIZE;
  • 当前长度:length;

地址计算方法:
第i个元素ai的存储地址:LOC(ai) = LOC(a1) +(i-1)*c; //c = sizeof(SqList);

*2、InitList(L),构建一个新的线性表

Status InitList_Sq(SqList &L){
	//构建一个空的线性表L;
	L.elem =(ElemType *)malloc(MAXSIZE*sizeof(ElemType));
	if( L == NULL)
		printf("申请内存失败\n");
	L.length = 0;    //空表长度为零
	L.listsize = MAXSIZE;//初始存储容量
	return OK;
}

3、ListEmpty(L),判断线性表是否为空

Status ListEmpty_Sq(SqList L){
	//判断线性表是否为空
	if(L.length == 0)
	return TRUE;
	else return FALSE;
}

*4、ClearList(L),清空线性表

Status ClearList_Sq(Sqlist &L){
	//清空线性表,需要找到表头位置,用到指针
	int i;
	for(i=0;i<L.length;i++)
		{
			L.elem[i]=0;
		}
		L.Length = 0;
	return OK;
}
	
	

*5、GetElem(L,i,e),查找线性表L第i个位置的元素并返回给e;

Status GetElem_Sq(SqList L, int i, ElemType *e) 
 {
 	if(L.length==0 || i<1 ||i>L.length )
 	{
 		return ERROR;
	 }
	 *e = L.elem[i-1];
	 return OK;
 }

6、LocateElem(L,e),在线性表中查找与给定e相等的元素

Status LocateELem_Sq(SqList L,ElemType e)
{
	int i;
	for(i=0;i<L.length;i++)
	{
		if(L.elem[i] == e)
		return i;
	}
	return ERROR;
}
	
	

**7、ListInsert(L,I,e):删除线性表L中的第i个元素,并用e返回其值

Status ListInsert_Sq(Sqlist *L,int i,ElemType *e)
{
	int k;
	
	if(L->length == MAXSIZE )  //顺序表已经满了
	{
		return ERROR;
	}
	if( i<1 || i>L->length+1 )  //当i不在范围内时
	{
		return ERROR;
	}
	if( i<=L->length )   //若插入数据位置不在表尾
	{
		/*将要插入位置后数据向后移动一位*/
		for( k=L->length-1; k>=i-1;k--)
		{
			L->elem[k+1] = L->elem[k];
		 } 
 } 
 L->elem[i-1] = e;   //将新元素插入
 L->length++;
 
 return OK; 
}
 

算法思路:

  • 若插入位置不合理,抛出异常
  • 若线性表长度大于数组长度,异常或扩容
  • 从最后一个元素开始遍历到第i个位置,分别将它们后移一位;
  • 将要插入元素填入i处
  • 线性表+1

8、ListDelete(*L,i,*e):删除线性表L中第i个元素,并用e返回其值

Status ListDelete_Sq(Sqlist *L,int i,ElemType *e)
{
	int k;
	
	if(L->length == 0 )  //顺序表为空 
	{
		return ERROR;
	}
	if( i<1 || i>L->length )  //当i不在范围内时
	{
		return ERROR;
	}
	*e = L->elem[i-1];    //取出要删除元素地址 
	 
	if( i<L->length )   //若删除数据位置不在表尾
	{
		/*将要插入位置后数据向前移动一位*/
		for( k=i; k < L->length; k++)  //???如何与插入操作区分? 
		{
			L->elem[k-1] = L->elem[k];
		 } 
 } 
 L->length--;
 
 return OK; 
}

算法思路:

  • 删除位置判断:不合理就抛出异常,否则继续
  • 取出删除元素
  • 从最后一位元素遍历到第i个位置,分别将它们前移一位
  • 返回要删除元素位置
  • 线性表长度-1

四、顺序存储结构的优缺点

  • 优点:可以快速的存取表中任意位置的元素,无需为表示元素之间的逻辑关系增加额外的存储空间(指针域);

  • 缺点:插入和删除需要移动大量的元素,当线性表变化较大时无法确定存储空间容量,已造成存储空间浪费。

五、综上线性表的整体代码

/* 顺序表练习 */
 #include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 20

 typedef int ElemType; 
 //顺序存储结构线性表结构代码 
 typedef struct
 {
 	ElemType elem[MAXSIZE];
 	int length;
 }SqList;
 

 typedef int Status;
 //Status 是函数的类型,其值是函数结果状态代码,如OK等
 //初始条件:顺序线性表L已存在,i<=i<=ListLength(L)
 //操作结果,用e返回L中第i个数据元素的值
 
 Status InitList_Sq(SqList *L){
	//构建一个空的线性表L;
	
	
	L->length = 0;    //空表长度为零
	return OK;
}

Status ListEmpty_Sq(SqList L){
	//判断线性表是否为空
	if(L.length == 0)
	return TRUE;
	else return FALSE;
}

Status ListLength_Sq(SqList *L){          //求长度
	return L->length; 
} 

Status ClearList_Sq(SqList *L){
	//清空线性表,需要找到表头位置,用到指针
	int i;
	for(i=0;i<L->length;i++)
		L->elem[i]=0;
		L->length = 0;
	return OK;
}


 
 Status GetElem(SqList L, int i, ElemType *e) 
 	//查找线性表L第i个位置的元素并返回给e 
 {
 	if(L.length==0 || i<1 ||L.length )
 	{
 		return ERROR;
	 }
	 *e = L.elem[i-1];
	 return OK;
 }
 
 Status LocateELem_Sq(SqList L,ElemType e)
 	//在线性表L中查找与给定e相等的元素 
{
	int i;
	for(i=0;i<L.length;i++)
	{
		if(L.elem[i] == e)
		return i;
	}
	return ERROR;
}

Status ListInsert_Sq(SqList *L,int i,ElemType *e)
	//删除线性表L中的第i个元素,并用e返回其值
{
	int k;
	
	if(L->length == MAXSIZE )  //顺序表已经满了
	{
		return ERROR;
	}
	if( i<1 || i>L->length+1 )  //当i不在范围内时
	{
		return ERROR;
	}
	if( i<=L->length )   //若插入数据位置不在表尾
	{
		/*将要插入位置后数据向后移动一位*/
		for( k=L->length-1; k>=i-1;k--)
		{
			L->elem[k+1] = L->elem[k];
		 } 
 } 
 L->elem[i-1] = *e;   //将新元素插入
 L->length++;
 
 return OK; 
}

Status ListDelete_Sq(SqList *L,int i,ElemType *e)
	//删除线性表L中第i个元素,并用e返回其值
{
	int k;
	
	if(L->length == 0 )  //顺序表为空 
	{
		return ERROR;
	}
	if( i<1 || i>L->length )  //当i不在范围内时
	{
		return ERROR;
	}
	*e = L->elem[i-1];    //取出要删除元素地址 
	 
	if( i<L->length )   //若删除数据位置不在表尾
	{
		/*将要插入位置后数据向前移动一位*/
		for( k=i; k < L->length; k++)  //???如何与插入操作区分? 
		{
			L->elem[k-1] = L->elem[k];
		 } 
 } 
 L->length--;
 
 return OK; 
}

Status DisplayList_Sq(SqList *L){          //输出表 
	if(L->length == 0)
	{
		return ERROR;
	}
	int i ;
	for(i = 1; i <= L->length; i++){
		printf("%2d ",L->elem[i]);
		if(i % 10 == 0) printf("\n");
	}
	printf("\n");
	return OK;
}


int main()
{
SqList list;
	InitList_Sq(&list);
	ElemType e; 
	printf("初始化顺序表:\n");
	printf("表长:%d\n",ListLength_Sq(&list));
	ListEmpty_Sq(list) == 1?printf("表空\n"):printf("表不空\n");
	printf("插入数字 1-10:\n"); 
	int i;
	for(i = 1; i <= 10; i++){
		e = i;
		ListInsert_Sq(&list,i,&e);
	}
	printf("表长:%d\n",ListLength_Sq(&list));
	ListEmpty_Sq(list) == 1?printf("表空\n"):printf("表不空\n");
	printf("输出顺序表:\n");
	DisplayList_Sq(&list);
	
	printf("在第1位插入9\n");
	 e = 9;
	ListInsert_Sq(&list, 1, &e);
	printf("输出顺序表:\n");
	printf("表长:%d\n",ListLength_Sq(&list));
	DisplayList_Sq(&list);
	
	printf("\n删除第10位\n");
	ListDelete_Sq(&list, 10, &e);
	printf("表长:%d\n",ListLength_Sq(&list));
	printf("输出顺序表:\n");
	DisplayList_Sq(&list);
	return 0;
}

注意:InitList()在最后的整体代码中没有用malloc()函数去分配初始地址:

L->elem[0] =(ElemType *)malloc(MAXSIZE*sizeof(ElemType));
//错误的,数组元素不不能直接赋值的,这种创建方式一般用在链表里面

Status InitList_Sq(SqList &L)
//这里的函数定义是错的,c++才允许这样传指针

正确写法:
Status InitList_Sq(SqList *L)

自己实践一边感觉收益良多。

发布了9 篇原创文章 · 获赞 9 · 访问量 256

猜你喜欢

转载自blog.csdn.net/Star_jiang/article/details/104716253