数据结构-顺序表

文章目录

一、顺序表的概念

        1.顺序存储概念

二、顺序表的实现

        1.静态顺序表的实现

                (1).静态顺序表的概念

                (2). 静态顺序表的结构体定义

                (3).静态顺序表初始化

                (4).静态顺序表获取元素

                (5).静态顺序表的插入操作

                (6).静态顺序表的删除操作

                (7).静态顺序表的改变元素操作

                (8).打印静态顺序表的元素

                (9).总代码

              (10).现象

        2.动态顺序表的实现

                (1).动态顺序表的概念

                (2).动态顺序表的空间判断

                (3). 动态顺序表的结构体定义

                (4).动态顺序表初始化

                (5).动态顺序表获取元素

                (6).动态顺序表的插入操作

                (7).动态顺序表的删除操作

                (8).动态顺序表的改变元素操作

                (9).打印动态顺序表的元素

              (10).总代码

              (11).现象

        3.顺序表的优缺点

               (1).优点

               (2).缺点


一、顺序表的概念

1.顺序存储概念

        顺序存储结构,是指用一段地址连续的存储单元依次存储线性表的数据元素。

2.存储方式

       在编程语言中,用一维数组来实现顺序存储,在c语言中,把第一个数据元素存储到下标为0的位置中,把第二个数据元素存储到下标为1的位置中,把第三个数据元素存储到下标为2的位置中,以此类推。

3.长度和容量

       数组的长度指的是数组当前有多少个元素,数组的容量指的是最大能够存放多少个元素。如果数组元素大于最大能存储。如果数组长度大于最大能存储的范围,在程序上是不允许的,可能会段错误,导致程序直接崩溃,实现上需要规避的。

二、顺序表的实现

1.静态顺序表

(1)静态顺序表概念

        静态顺序顺序表的概念就是,顺序表的数组容量是固定不变的,当顺序表的数组满了,就不能再存储元素了。

(2)静态顺序表的结构体定义

#define MAXSIZE 20             /*存储空间的初始分配量*/
typedef int ElemType;		   /*ElemType类型根据实际情况而定,这里为int*/ 
typedef struct sqlist                
{
	ElemType data[MAXSIZE];   /*数组,存储数据元素*/
	int length;				   /*线性表当前长度*/
}sqlist;

#define OK 1
#define ERROR 0
typedef int Status;  /*Status是函数的类型,其值是函数结果状态代码,如OK等*/

        ·(1)数据类型为Elemtype,定义为int;

        ·(2)sqlist定义的就是一个最多存放MAXSIZE元素的数组,MAXSIZE代表数组容量;

        ·  (3) length代表数组长度,即当前的元素个数;

        · (4) Status代表函数的类型。

(3)静态顺序表初始化

/*函数功能:顺序表初始化*/                            
/*初始条件:无*/
/*操作结果:无*/
sqlist* listinit()
{
	sqlist *L=(sqlist* )malloc(sizeof(struct sqlist));
	bzero(L->data,MAXSIZE);
	L->length=0;
	return L;
}

   注意:此处返回的类型是顺序表结构体指针。

(4)静态顺序表获取元素

/*函数功能:获取元素*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:用e返回L中第i个元素的值,注意i指的是位置,第一个位置的数组是从0开始*/
Status getELem(sqlist* L, int i, ElemType *e)
{
	if(L->length==0 || i<1 || i>L->length)
		return ERROR;
	*e=L->data[i-1];
	
	return OK;
}

            ·(1)L是顺序表的结构体指针;

            ·(2)i是你要获得的第几个元素的位置注意i指的是位置,第一个位置的数组是从0开始;

            ·  (3) e元素指针,将获取的元素赋值给e指向的变量。

(5)静态顺序表的插入操作

/*函数功能:插入操作*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1*/
Status ListInsert(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; k--)	/*将要插入位置后的元素,向后移一位*/
		{
			L->data[k+1]=L->data[k];    /*将新元素插入*/
		}
	}
	L->data[i-1]=e;
	L->length++;   
	
	return OK;
}

        ·(1)L是顺序表的结构体指针;

       · (2)i是你要插入的位置,这里i的指的位置与上面的一样;

       · (3)e是你要插入的元素

(6)静态顺序表的删除操作

/*函数功能:删除元素*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:删除L的第i个数据元素,并用e返回其值,L的长度见减1*/
Status 	ListDelete(sqlist *L, int i, ElemType *e)
{
	int k;
	if(L->length==0) 					/*线性表为空*/
		return ERROR;					
	if(i<1 || i>L->length)				/*删除位置不准确*/
		return ERROR;
	*e=L->data[i-1];
	if(i<L->length)						/*如果删除不是最后的位置*/
	{
		for(k=i; k<L->length; k++)		/*将删除位置后继元素前移*/
		{
			L->data[k-1]=L->data[k];
		}
	}
	
	L->length--;
	return OK;
}

        ·(1)L是顺序表的结构体指针;

        · (2)i是你要删除的位置,这里i的指的位置与上面的一样;

        ·  (3) e元素指针,将获取的元素赋值给e指向的变量。

(7)静态顺序表的改变元素操作

//函数功能:改变元素
//初始条件:无
//操作结果:将直接改变对应元素的值
Status ListChange(sqlist* L, ElemType oldnum, ElemType newnum)
{
	int k=0;
	for(k=0; k<L->length; k++)   //遍历找到要修改的元素oldnum,
	{
		if(L->data[k]==oldnum)
		{
			L->data[k]=newnum;   //将oldnum替换为newnum
			return OK;
		}
	}
	return ERROR;
} 

        ·(1)L是顺序表的结构体指针;

        ·(2)oldnum原来的元素

        ·(3)newnum新的元素

(8)打印静态顺序表的元素

//此函数只适用于元素类型为int
//函数功能:遍历顺序表
//初始条件:顺序表不为空;
//操作结果:打印出线性表
void listprintf(sqlist *L)
{
	int k=0;
	for(k=0; k<L->length; k++)
	{
		printf("第%d个元素: %d\n", k, L->data[k]);
	}
}

        注意:此函数只适合元素类型为int

     ·(1)L是顺序表的结构体指针;

(9)总代码

#include "stdio.h"
#include <stdlib.h>
#include <strings.h>


//结构体定义
#define MAXSIZE 20             /*存储空间的初始分配量*/
typedef int ElemType;		   /*ElemType类型根据实际情况而定,这里为int*/ 
typedef struct sqlist                
{
	ElemType data[MAXSIZE];   /*数组,存储数据元素*/
	int length;				   /*线性表当前长度*/
}sqlist;

#define OK 1
#define ERROR 0
typedef int Status;  /*Status是函数的类型,其值是函数结果状态代码,如OK等*/


/*函数功能:顺序表初始化*/                            
/*初始条件:无*/
/*操作结果:无*/
sqlist* listinit()
{
	sqlist *L=(sqlist* )malloc(sizeof(struct sqlist));
	bzero(L->data,MAXSIZE);
	L->length=0;
	return L;
}

/*函数功能:获取元素*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:用e返回L中第i个元素的值,注意i指的是位置,第一个位置的数组是从0开始*/
Status getELem(sqlist* L, int i, ElemType *e)
{
	if(L->length==0 || i<1 || i>L->length)
		return ERROR;
	*e=L->data[i-1];
	
	return OK;
}

/*函数功能:插入操作*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1*/
Status ListInsert(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; k--)	/*将要插入位置后的元素,向后移一位*/
		{
			L->data[k+1]=L->data[k];    /*将新元素插入*/
		}
	}
	L->data[i-1]=e;
	L->length++;   
	
	return OK;
}

/*函数功能:删除元素*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:删除L的第i个数据元素,并用e返回其值,L的长度见减1*/
Status 	ListDelete(sqlist *L, int i, ElemType *e)
{
	int k;
	if(L->length==0) 					/*线性表为空*/
		return ERROR;					
	if(i<1 || i>L->length)				/*删除位置不准确*/
		return ERROR;
	*e=L->data[i-1];
	if(i<L->length)						/*如果删除不是最后的位置*/
	{
		for(k=i; k<L->length; k++)		/*将删除位置后继元素前移*/
		{
			L->data[k-1]=L->data[k];
		}
	}
	
	L->length--;
	return OK;
}

//函数功能:改变元素
//初始条件:无
//操作结果:将直接改变对应元素的值
Status ListChange(sqlist* L, ElemType oldnum, ElemType newnum)
{
	int k=0;
	for(k=0; k<L->length; k++)   //遍历找到要修改的元素oldnum,
	{
		if(L->data[k]==oldnum)
		{
			L->data[k]=newnum;   //将oldnum替换为newnum
			return OK;
		}
	}
	return ERROR;
} 




//此函数只适用于元素类型为int
//函数功能:遍历顺序表
//初始条件:顺序表不为空;
//操作结果:打印出线性表
void listprintf(sqlist *L)
{
	int k=0;
	for(k=0; k<L->length; k++)
	{
		printf("第%d个元素: %d\n", k, L->data[k]);
	}
}


int main()
{
//元素的插入	
	sqlist* L=listinit();
	ListInsert(L, 1, 1);
	ListInsert(L, 2, 2);	
	ListInsert(L, 3, 3);		
	listprintf(L);

//元素的删除	
	int e;
	e=ListDelete(L, 1, &e);
	printf("%d\n", e);
	listprintf(L);	

//获取元素	
	getELem(L,1,&e);
	printf("%d\n", e);	
	
//改变元素的值
	ListChange(L,2,5);
	listprintf(L);
}

(10)现象

第0个元素: 1
第1个元素: 2
第2个元素: 3
1
第0个元素: 2
第1个元素: 3
2
第0个元素: 5
第1个元素: 3

1.动态顺序表

(1)动态顺序表概念

        动态顺序表的概念就是,顺序表的数组容量不是固定不变的,当顺序表的数组满了,它能够自己增加顺序表的容量,不用担心数组越界的问题

(2)静态顺序表的结构体定义

//结构体定义
typedef int ElemType;		   /*ElemType类型根据实际情况而定,这里为int*/ 
typedef struct sqlist                
{
	ElemType *data;           /*定义一个元素指针*/
	int length;				  /*线性表当前长度*/
	int capacity;             /*顺序表当前容量*/
}sqlist;

#define OK 1
#define ERROR 0
typedef int Status;  /*Status是函数的类型,其值是函数结果状态代码,如OK等*/

        ·(1)数据类型为Elemtype,定义为int;

       · (2)data是一个元素指针,用来当数组的首地址

       · (3) length代表数组长度,即当前的元素个数;

       · (4)capacity是顺序表容量

       · (5)Status代表函数的类型。

(3)动态顺序表初始化

/*函数功能:顺序表初始化*/
/*初始条件:无*/
/*操作结果:无*/
sqlist* listinit()
{
	sqlist *L=(sqlist* )malloc(sizeof(struct sqlist));   //初始化结构体
	L->capacity=4;       								 //存储空间的初始分配量4
	L->data=malloc(sizeof(ElemType)*L->capacity);        //分配数组长度为4
	L->length=0;										 //数组长度初始化为0
	return L;
}

   注意:此处返回的类型是顺序表结构体指针。

(4)动态顺序表的空间判断

//函数功能:判断顺序表空间是否还有空间
//初始条件:无
//操作结果:
Status listcheck(sqlist* L)
{
	if(L->length>=L->capacity)
	{
		L->capacity*=2;
		L->data=realloc(L->data,L->capacity);
		return ERROR;
	}
	return OK;
}

        ·(1)L是顺序表的结构体指针;

(5)动态顺序表获取元素

/*函数功能:获取元素*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:用e返回L中第i个元素的值,注意i指的是位置,第一个位置的数组是从0开始*/
Status getELem(sqlist* L, int i, ElemType *e)
{
	if(L->length==0 || i<1 || i>L->length)
		return ERROR;
	*e=L->data[i-1];
	
	return OK;
}}

            ·(1)L是顺序表的结构体指针;

            ·(2)i是你要获得的第几个元素的位置注意i指的是位置,第一个位置的数组是从0开始;

            ·  (3) e元素指针,将获取的元素赋值给e指向的变量。

(6)动态顺序表的插入操作

/*函数功能:插入操作*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1*/
Status ListInsert(sqlist *L, int i, ElemType e)
{
	listcheck(L);                      //检查顺序表容量是否足够
	int k;
	if(i<1 || i>L->length+1)		   /*当i比第一位置小或者比最后一位后一位置还要大的时候*/
	{
		return ERROR;				   /*如果插入位置不在表尾*/
	}
	
	if(i<=L->length)                  //如果插入的位置是当前长度,跳过这一步
	{
		for(k=L->length-1; k>=i; k--)	/*将要插入位置后的元素,向后移一位*/
		{
			L->data[k+1]=L->data[k];    /*将新元素插入*/
		}
	}
	L->data[i-1]=e;
	L->length++;   
	
	return OK;
}

        ·(1)L是顺序表的结构体指针;

       · (2)i是你要插入的位置,这里i的指的位置与上面的一样;

       · (3)e是你要插入的元素

(7)动态顺序表的删除操作

/*函数功能:删除元素*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:删除L的第i个数据元素,并用e返回其值,L的长度见减1*/
Status 	ListDelete(sqlist *L, int i, ElemType *e)
{
	int k;
	if(L->length==0) 					/*线性表为空*/
		return ERROR;					
	if(i<1 || i>L->length)				/*删除位置不准确*/
		return ERROR;
	*e=L->data[i-1];
	if(i<L->length)						/*如果删除不是最后的位置*/
	{
		for(k=i; k<L->length; k++)		/*将删除位置后继元素前移*/
		{
			L->data[k-1]=L->data[k];
		}
	}
	
	L->length--;
	return OK;
}

        ·(1)L是顺序表的结构体指针;

        · (2)i是你要删除的位置,这里i的指的位置与上面的一样;

        ·  (3) e元素指针,将获取的元素赋值给e指向的变量。

(8)动态顺序表的改变元素操作

//函数功能:改变元素
//初始条件:无
//操作结果:将直接改变对应元素的值
Status ListChange(sqlist* L, ElemType oldnum, ElemType newnum)
{
	int k=0;
	for(k=0; k<L->length; k++)   //遍历找到要修改的元素oldnum,
	{
		if(L->data[k]==oldnum)
		{
			L->data[k]=newnum;   //将oldnum替换为newnum
			return OK;
		}
	}
	return ERROR;
} 

        ·(1)L是顺序表的结构体指针;

        ·(2)oldnum原来的元素

        ·(3)newnum新的元素

(9)打印动态顺序表的元素

//此函数只适用于元素类型为int
//函数功能:遍历顺序表
//初始条件:顺序表不为空;
//操作结果:打印出线性表
void listprintf(sqlist *L)
{
	int k=0;
	for(k=0; k<L->length; k++)
	{
		printf("第%d个元素: %d\n", k, L->data[k]);
	}
}

        注意:此函数只适合元素类型为int

     ·(1)L是顺序表的结构体指针;

(10)总代码

#include "stdio.h"
#include <stdlib.h>
#include <strings.h>

//结构体定义
typedef int ElemType;		   /*ElemType类型根据实际情况而定,这里为int*/ 
typedef struct sqlist                
{
	ElemType *data;           /*定义一个元素指针*/
	int length;				  /*线性表当前长度*/
	int capacity;             /*顺序表当前容量*/
}sqlist;

#define OK 1
#define ERROR 0
typedef int Status;  /*Status是函数的类型,其值是函数结果状态代码,如OK等*/

//函数功能:判断顺序表空间是否还有空间
//初始条件:无
//操作结果:
Status listcheck(sqlist* L)
{
	if(L->length>=L->capacity)
	{
		L->capacity*=2;
		L->data=realloc(L->data,L->capacity);
		return ERROR;
	}
	return OK;
}



/*函数功能:顺序表初始化*/
/*初始条件:无*/
/*操作结果:无*/
sqlist* listinit()
{
	sqlist *L=(sqlist* )malloc(sizeof(struct sqlist));   //初始化结构体
	L->capacity=4;       								 //存储空间的初始分配量4
	L->data=malloc(sizeof(ElemType)*L->capacity);        //分配数组长度为4
	L->length=0;										 //数组长度初始化为0
	return L;
}

/*函数功能:获取元素*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:用e返回L中第i个元素的值,注意i指的是位置,第一个位置的数组是从0开始*/
Status getELem(sqlist* L, int i, ElemType *e)
{
	if(L->length==0 || i<1 || i>L->length)
		return ERROR;
	*e=L->data[i-1];
	
	return OK;
}

/*函数功能:插入操作*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1*/
Status ListInsert(sqlist *L, int i, ElemType e)
{
	listcheck(L);                      //检查顺序表容量是否足够
	int k;
	if(i<1 || i>L->length+1)		   /*当i比第一位置小或者比最后一位后一位置还要大的时候*/
	{
		return ERROR;				   /*如果插入位置不在表尾*/
	}
	
	if(i<=L->length)                  //如果插入的位置是当前长度,跳过这一步
	{
		for(k=L->length-1; k>=i; k--)	/*将要插入位置后的元素,向后移一位*/
		{
			L->data[k+1]=L->data[k];    /*将新元素插入*/
		}
	}
	L->data[i-1]=e;
	L->length++;   
	
	return OK;
}

/*函数功能:删除元素*/
/*初始条件:顺序线性表L已存在,1<=i<listlength(L)*/
/*操作结果:删除L的第i个数据元素,并用e返回其值,L的长度见减1*/
Status 	ListDelete(sqlist *L, int i, ElemType *e)
{
	int k;
	if(L->length==0) 					/*线性表为空*/
		return ERROR;	
	if(i<1 || i>L->length)				/*删除位置不准确*/
		return ERROR;
	*e=L->data[i-1];
	if(i<L->length)						/*如果删除不是最后的位置*/
	{
		for(k=i; k<L->length; k++)		/*将删除位置后继元素前移*/
		{
			L->data[k-1]=L->data[k];
		}
	}
	
	L->length--;
	return OK;
}

//函数功能:改变元素
//初始条件:无
//操作结果:将直接改变对应元素的值
Status ListChange(sqlist* L, ElemType oldnum, ElemType newnum)
{
	int k=0;
	for(k=0; k<L->length; k++)   //遍历找到要修改的元素oldnum,
	{
		if(L->data[k]==oldnum)
		{
			L->data[k]=newnum;   //将oldnum替换为newnum
			return OK;
		}
	}
	return ERROR;
} 




//此函数只适用于元素类型为int
//函数功能:遍历顺序表
//初始条件:顺序表不为空;
//操作结果:打印出线性表
void listprintf(sqlist *L)
{
	int k=0;
	for(k=0; k<L->length; k++)
	{
		printf("第%d个元素: %d\n", k, L->data[k]);
	}
}


int main()
{
//元素的插入	
	sqlist* L=listinit();
	ListInsert(L, 1, 1);
	ListInsert(L, 2, 2);	
	ListInsert(L, 3, 3);
	ListInsert(L, 4, 4);
	ListInsert(L, 5, 5);	
	ListInsert(L, 6, 6);	
	listprintf(L);

//元素的删除	
	int e;
	e=ListDelete(L, 1, &e);
	printf("%d\n", e);
	listprintf(L);	

//获取元素	
	getELem(L,1,&e);
	printf("%d\n", e);	
	
//改变元素的值
	ListChange(L,2,5);
	listprintf(L);
}

(11)现象

第0个元素: 1
第1个元素: 2
第2个元素: 3
第3个元素: 4
第4个元素: 5
第5个元素: 6
1
第0个元素: 2
第1个元素: 3
第2个元素: 4
第3个元素: 5
第4个元素: 6
2
第0个元素: 5
第1个元素: 3
第2个元素: 4
第3个元素: 5
第4个元素: 6

 3.顺序表的优缺点

(1)优点

        ·无须为表示表中元素之间的逻辑关系二而增加额外的存储空间

       ·可以迅速地获取表中任一位置的元素

(2)缺点

       · 插入和删除操作需要移动大量元素

       ·当线性表长度变化较大时,难以确定存储空间的容量,静态顺序表可能导致容量不够,动态顺序表可能导致存储空间的浪费

       

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值