线性表的顺序存储--C语言(学习笔记)

一、线性表定义

线性表(List) 定义: 是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

注意:

1)线性表是一个序列。也就是说, 线性表的元素之间是有序的。若元素存在多个,对于其中一个元素来说,他前一个的元素叫前驱,后一个元素叫后继。第一个元素无前驱,最后一个元素无后继。其它元素只有一个前驱,一个后继。

2)线性表是有限的,事实上,在计算机科学领域,我们只研究有限的序列,因为计算机的处理对象都是有限的。而对那些无限的序列,只存在数学讨论。(简单来说,就是计算机内存有限)

3)线性表的元素个数n(n>=0)定义为该线性表的长度。当n=0时,称为空表。

二、顺序表

为什么要学习线性表中顺序表,有什么作用?

 依我的理解,顺序表相当于数组的升级版。

数组:线性结构。可以存储、赋值、修改里面空间的数据。但数组不能插入,删除等操作。因此,为了满足工作的需要,需要学习顺序表。

 线性表的顺序存储--C语言(学习笔记)_第1张图片

那么如何使用顺序表,表示上图数据呢

请你接着往下看。

首先,我需要知道顺序表有哪几部分。上面说了,顺序表是数组的升级版。我们可以得知,数组有的东西,顺序表也有。从data[8]这图看,有格子,也就是数组长度、有名字、还有数据。

因此,

 顺序表结构里面拥有表长和数据内容。


二、顺序表的表长(length)与 数组长度的区别:

        表长:顺序表内有效元素个数(如上表data,有效元素有5个,即length=5)

 表长与 数组长度的区别

        1)表长是变量,数组长度是常量(变量是可以按需求来更改。而数组定义了多长,就是多长,所以是常量)

        2)表长表示当前顺序表内有效元素个数,因此变量表长时刻小于等于数组长度

三、顺序表的创建与使用

1、顺序表结构搭建,创建一个结构体。

#define MAX 8                //MAX就是8

typedef struct
  {
     
      int data[MAX];       //表的最大长度。MAX是8,有8个格子存储数据
      int length;          //表长,即表内有效元素的个数
      
    
  }sqlist;

2、顺序表初始化,即格式化  CreateEmptySqlist()

sqlist *CreateEmptySqlist()         //创建一个空的顺序表
{
     sqlist *sq;
     
     
//问题1:为什么需要使用malloc函数,把CreateEmptySqlist() 函数开辟在堆区
// 答:本函数CreateEmptySqlist()在main函数外创建的,属于局部变量。在栈区中。
// 如果不使用malloc函数,此函数程序运行结束,该创建的顺序表,会被释放掉。
// 无法被后面的程序再次调用。
      
     if(sq = (sqlist *)mallac(sizeof(sqlist)))==NULL)      
    {
        
        perror("fail to malloc");
        exit(1);
    }
//问题2:为什么要写 sq->length = 0。可以不写?
//答:1)从编码角度,如果不写,里面的数据会出现乱码,无法被后面的程序使用。
// 2)从逻辑角度,本次函数名CreateEmptySqlist,叫创建一个空的顺序表,必须sq->length = 0
        sq->length = 0;
    return sq;//sq是sqlist的指针,所以函数名得加  sqlist *CreateEmptySqlist()
    
}

线性表的顺序存储--C语言(学习笔记)_第2张图片

 3、 给表赋值,表示下图data[8]={1,2,3,4,5};

#define  MAX 20
#define OK 1
#define ERROR 0

sqlist *AssignmentList(sqlist *sq)
{
     int i;

     printf("请输入你需要的顺序表长度:\n")
    
     scanf("%d",sq->length);

     if(sq->length < 0 || sq->length > MAX )
  {

      printf("线性表的长度超了最大长度!!!");
      return ERROR;
  }
    else
  {
       printf("请输入顺序表的数据:\n");
      for(i=0;i<8;i++)
      {
        scanf("%d",sq->data[i]);
      }
      printf("顺序表赋值完成\n");
  }
      return sq;

}
//假设此代码,已经齐全了
//程序开始执行
//********************

//请输入你需要的顺序表长度
// 5
//请输入顺序表的数据
//  1
//  2
//  3
//  4
//  5
//  6
//  7
//  8
//运行结束,因为有效长度为5,因此后面输入的6,、7、8都是无效的,表内的数据 等效 data[8]

4、查找元素GetElement

//查找元素 GetElement
#define OK 1
#define ERROR 0

//问题1;为什么需要 int *e;
//表内有效元素里,存在零这个数据,但主函数不清楚这个返回的零是失败的结果还是有效数据里的零。
//需要用地址传参,返回给主函数判断,这个零到底是返回失败的结果,还是表里有效数据里的零 。
int GetElement(sqlist *sq,int i , int *e)  
 {

   if(i < 0 || i>= sq->length)    //判断元素的位置是否在表内
  {

    printf("no element\n");     
    return ERROR; 
   }
    (*e) = sq->data[i];      / 
    return OK;
  }
  int main()
  
{
   sqlist *sq;
   
    int data;
    sq = CreateEmptyList();
    //假设这表已经有n个数据
    if( GetElement(sq, 3,&data)==OK)    
    {
       printf("GetElement()return success\n");   
   }
    else
    { 
      printf("GetElement()return fail\n"); 
     }   
}

5、插入元素(按位置)

//插入元素(按位置)
#define OK 1
#define ERROR 0

int InsertList(sqlist *sq,int i,int e) //调用该结构体,即获取表内的数据;插入的位置;插入的元素
{
   int k;                   
   if(sq->length==MAX)
 {
   printf("fill list\n");   //判断表是否满了,通俗的讲,表里面的每个格子都有元素了,即为表满
	
      return ERROR;
 }
   if(i<0 || i>sq->length)   //判断插入的元素位置,是否越界
 {  
    printf("input error\n ");

	 return ERROR; 
 }
	for(k=sq->length-1;k>=i ; k--)   //先从表内最后一位有效元素后移一位
	{                                    
	     sq->data[k+1]=sq->data{k};     
	}
	 sq->data[k]=e;
	 sq->length++;      //插入一个元素,表内的有效数据加1,即有效长度length加1
	
     return OK;
}

6、删除元素(按位置)DeleteList

//删除元素(按位置)DeleteList

int DeleteList(sqlist *sq, int i ,int *e)
{
   int k;
   if(sq->length==0)            //判断该表 是否为空,空表无元素,无元素可删
  {
   printf("empty list\n");   
   return ERROR;
  }

   if(i<0 || i>sq->length)      //判断该表获取取的位置是否越界
  {
   printf("delete error\n");
   return ERROR;
  }
    *e = sq->data[i-1];          //把删除的元素给*e
   for(k=i; k < q->length; k++)
   {
     sq->data[k-1]=sq->data[k];  //后面的元素往前移一位
   }
     sq->length--;               //删掉一个元素,有效表长length 需要减1

     return OK;                 
}

 7、清空表ClearList

清空表ClearList

void ClearList(sqlist *sq)
{
   sq->length=0;      //表长为0,里面存在的数据,有也是无效的
}

四、完整代码

#include 
#include
#include

#define MAX 20                  //MAX就是20
#define ERROR 0
#define OK 1
typedef struct
{
     
      int data[MAX];       //表的最大长度
      int length;          //表长,即有表内效元素个数
      
 }sqlist;

sqlist *CreateEmptySqlist()         //创建一个空的顺序表
{
     sqlist *sq;
     if( (sq =(sqlist *)malloc(sizeof(sqlist)))==NULL)      
    {
        
        perror("fail to malloc");
        exit(1);
    }
        sq->length = 0;
	 int i;
     
     printf("请输入你需要的顺序表长度:\n");
    
     scanf("%d",&sq->length);

     if(sq->length < 0 || sq->length > MAX )
  {

      printf("线性表的长度超了最大长度!!!\n");
      return ERROR;
  }
    else
  {
       printf("请输入顺序表的数据:\n");
      for(i=0;ilength;i++)
      {
        scanf("%d",&sq->data[i]);
      }
      printf("顺序表赋值完成\n");
  }
    return sq;    
}

  int main()
  {
     int k;
     sqlist *sq;
     sq = CreateEmptySqlist(); 
	 printf("length = %d\n",sq->length);         //查看表的有效长度
     for(k=0 ;k < sq->length ;k++ )              //查看表内的元素
    {
	  	printf("sq->data[%d]=%d\n",k,sq->data[k]); 	
		}
     
     return 0;
  }

运行结果: 

            请输入你需要的顺序表长度:
            5
            请输入顺序表的数据:
            1
            2
            3

            4
            5
            顺序表赋值完成
            length = 5
            sq->data[0]=1
            sq->data[1]=2
            sq->data[2]=3
            sq->data[3]=4
            sq->data[4]=5

 此图可表示该代码的顺序表结构,一共有20个格子,只使用了5个格子。可插入数据,删除数据,清空数据等操作

 五、总结

1. 顺序表优点
节省存储空间,因为结点之间的逻辑关系没有占用额外的存储空间。
2. 顺序表缺点
顺序存储方法不便于修改,对结点的插入、删除运算时,需要移动一系列的结点。

你可能感兴趣的:(数据结构,算法,数据结构)