线性表结构一——顺序表初始化,插入,删除,查找。typedef 解释,链表知识点总结

目录

一、顺序表定义及特点

1.顺序表定义

2.顺序表特点

二、顺序表定义

三、顺序表插入运算

四、顺序表删除运算

五、顺序表元素查找

六、顺序表取元素数据

七、主函数定义

注1. typedef 解释

注2. 链表知识点总结


一、顺序表定义及特点

 

1.顺序表定义

用数组存储线性表,称作线性表的顺序存储结构或顺序映像,用这种方法存储的线性表称作顺序表。

2.顺序表特点

1)逻辑上相邻,对应物理地址相邻

2)任一元素可以随机存取

3)容量难以扩充,插入、删除操作复杂

二、顺序表定义

//顺序表定义
typedef int ElemType;           //顺序表元素类型为整形
const int LIST_SIZE = 1024;     //顺序表最大长度为1024
typedef struct sequen
{
    ElemType data[LIST_SIZE];   //顺序表所要存储的数据
    int last;                   //指向顺序表最后一位数据的指针
}SeqList;                       //结构体别名,在主函数中可以有声明变量 SeqList list;
SeqList* LPtr;                  //定义顺序表指针变量

关于 typedef 的解释可详见下方的注释1.

三、顺序表插入运算

一般情况下,要在第 i(1 <= i <= n)个元素之前插入一个新元素时,首先要从最后一个元素开始,直到第 i 个元素之间共n - i + 1 个元素依次向后移动一个位置。移动结束后,第 i 个位置就被空出,然后将新元素插入,插入结束线性表的长度增加1。

/*=================================================
函数功能:顺序表运算——元素的插入
函数输入:顺序表地址,插入值,插入位置
函数输出:完成标志—— 0:异常  1:正常
=================================================*/
int Insert_SqList(SeqList *Lptr, ElemType x, int k)
{
    if(Lptr->last >= LIST_SIZE - 1)             //判断是否内存溢出
        return false;
    else if(k < 0 || k > (Lptr->last + 1))      //插入点为非法位置
        return false;
    else
    {
        for(int i = Lptr->last; i >= k; i--)
            Lptr->data[i + 1] = Lptr->data[i];
        Lptr->data[k] = x;                      //将 X 放入第 k 个位置
        Lptr->last = Lptr->last + 1;            //修改最后结点指针 last
    }
    return true;
}

四、顺序表删除运算

在顺序表上实现删除运算也需要移动结点,以填补删除操作造成的空缺,从而保证删除后的元素间依然通过物理地址相邻而体现逻辑相邻关系。若 1 <= i <= n - 1,必须将表中位置 i + 1, i + 2, ..., n的结点,依次前移到位置 i, i + 1, ..., n - 1上,需将 i + 1至第 n 共n - 1个元素前移。

/*=================================================
函数功能:顺序表运算——元素的删除
函数输入:顺序表地址,删除位置
函数输出:完成标志—— 0:异常  1:正常
=================================================*/
int Delete_SqList(SeqList *Lptr, int k)
{
    if((k >= 0 && k <= Lptr->last) && (Lptr->last != 0))
    {
        for(int i = k; i <= Lptr->last; i++)
            Lptr->data[i] = Lptr->data[i + 1];
        Lptr->last--;
        return true;
    }
    return false;
}

五、顺序表元素查找

从第一个元素开始,逐个把元素的关键字值和给定值比较,若某个元素的关键字值和给定值相等,则查找成功;否则,若直至第n个记录都不相等,说明不存在满足条件的数据元素,查找失败。

/*=================================================
函数功能:顺序表运算——查找给定的值
函数输入:顺序表地址,结点值
函数输出:完成标志—— 正常:下标值  异常:-1
=================================================*/
int Locate_SqList(SeqList *Lptr, ElemType key)
{
    for(int i = 0; i < Lptr->last; i++)
        if(Lptr->data[i] == key)
            return i;
    return false;
}

六、顺序表取元素数据

由于顺序表是数组结构,属于随机存取结构,故已知下标就可以直接得到对应的数组元素值,只需要注意判断给定的下标是否出界即可。

/*=================================================
函数功能:顺序表运算——取给定下标的元素值
函数输入:顺序表地址,下标位置,下标元素数据
函数输出:完成标志—— 异常:-1  正常:下标元素数据
=================================================*/
int Get_SqList(SeqList *Lptr, int k, ElemType e)
{
    if(k < 0 || k > Lptr->last)
        return false;
    if(Lptr->last < 0)
        return false;
    e = Lptr->data[k];
    return e;
}

七、主函数定义

int main(int argc, const char * argv[])
{
    //线性表初始化
    //SeqList list = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 10}; //另一种初始化方法
    SeqList* list = (SeqList *)malloc(sizeof(SeqList));    //在调用时必须如申请指针必须开辟内存空间
    int j = 0;
    for(int i = 0; i < 10; i++)
    {
        list->data[i] = i;
        j++;
    }
    list->last = j;
    
    //线性表运算
    Insert_SqList(list, 11, 5);
    //Insert_SqList(&list, 11, 5);
    Delete_SqList(list, 6);
    ElemType e = 0;                                        //局部变量定义时一定要初始化
    e = Get_SqList(list, 5, e);
    //ElemType e = Get_SqList(list, 5, e);                 //另一种表示方法
    
    //线性表数据打印
    for(int i = 0; i < list->last; i++)                    //打印表中的数据
    {
        cout<< list->data[i] << "\t"<注1. typedef 解释 
  

typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。

在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。

至于typedef有什么微妙之处,请你接着看下面对几个问题的具体阐述。

2. typedef & 结构的问题

当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明:

typedef struct tagNode
{
char* pItem;
pNode* pNext;
}pNode;

分析:

1、typedef的最简单使用

typedef long byte_4;

给已知数据类型long起个新名字,叫byte_4。

2、 typedef与结构结合使用

typedef struct tagMyStruct
{
int iNum;
long lLength;
}MyStruct;

这语句实际上完成两个操作:

1) 定义一个新的结构类型

struct tagMyStruct
{
int iNum;
long lLength;
};

分析:tagMyStruct称为“tag”,即“标签”,实际上是一个临时名字,struct关键字和tagMyStruct一起,构成了这个结构类型,不论是否有typedef,这个结构都存在。

我们可以用struct tagMyStruct varName来定义变量,但要注意,使用tagMyStruct varName来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。

2) typedef为这个新的结构起了一个名字,叫MyStruct。

typedef struct tagMyStruct MyStruct;

因此,MyStruct实际上相当于struct tagMyStruct,我们可以使用MyStruct varName来定义变量。

答案与分析

C语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用。

根据我们上面的阐述可以知道:新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode。

解决这个问题的方法有多种:

//方法一
typedef struct tagNode
{
char* pItem;
struct tagNode* pNext;
}*pNode;

//方法二
typedef struct tagNode* pNode;
struct tagNode
{
char* pItem;
pNode pNext;                      //这边不用pNode* ,pNode 已经表示了struct tagNode*
};

//方法三,规范做法
struct tagNode
{
char* pItem;
struct tagNode* pNext;
};
typedef struct tagNode* pNode;

注2. 链表知识点总结

https://blog.csdn.net/qq_41291253/article/details/89218736

你可能感兴趣的:(#,C++容器详解,顺序表,线性表,顺序表插入,顺序表删除,顺序表查找)