线性表的初级认识

目录:

一,线性表的定义

二,线性表的基本运算

三,线性表中的顺序表

四,线性表中的链式表


一,线性表的定义

        线性表是最为基础的逻辑结构,是n个相同属性元素的有限序列,而数据元素在线性表中的位置取决于它自身的序号,它所对应的逻辑结构如图:

线性表的初级认识_第1张图片

               通常我们需要设置一系列连续的数据时使用线性表。

二,线性表的基本运算

        线性表的运算方式复杂多样,种类也繁多,但对于初学者来说,线性表的常用运算我进行了一下总结:

(1)设置基础的线性表

(2)增添线性表中的数据元素

(3)展示线性表中的数据元素

(4)删除线性表中的数据元素

(5)查找线性表中的数据元素

(6)修改线性表中的数据元素

        线性表虽然有不同的种类,但对于初学者的基本操作都基本归于以上几种类型

三,线性表中的顺序表

        首先,我们先来介绍一下线性表中的顺序表。顺序表是用来存储线性表最简单,最常用的方式,是在计算机中开辟一系列连续的内存空间进行存储不同的数据元素。顺序表具有物理相邻的特点。我们之前设置的基础通讯录就运用的是顺序表。下面,我以C++中的通讯录设置的算法来跟大家演示一下顺序表中的基本运算:

(1)设置基础的线性表,在这里我以结构体的形式设置,也可用数组的形式,但设置起来比较麻烦,思路基本相同。

//首先,设置通用的数据元素,即线性表的数据元素

struct person
{
    string name;
    int sex;
    int age;
    string phone;
    string number;
    string address;
};

//然后,用数组的形式将一系列数据元素构成线性表

struct add
{
    struct person arr[m];
    int size;
}a;

(2)增添线性表中的数据元素,要考虑线性表是否满载的情况,具体方法如下

void addperson(struct add* a,int* p)//基础运算中的增添算法
{
    if (a->size == m)//当线性表满了时候的情况
    {
        cout << "通讯录存放已满,无法添加" << endl;
        return;
    }
    else//当线性表没有存储满时进行增加数据元素
    {
        //姓名
        cin >> a->arr[*p].name;
        //性别
        cout << "1,男\n" << "2,女" << endl;
        while (true)
        {
            int select;
            cin >> select;
            if (select == 1 || select == 2)
            {
                if (select == 1)
                    a->arr[*p].sex = 1;
                else
                    a->arr[*p].sex = 2;
                break;
            }
        }
        //年龄
        cin >> a->arr[*p].age;
        //电话
        cin >> a->arr[*p].phone;
        //身份证号
        cin >> a->arr[*p].number;
        //地址
        cin >> a->arr[*p].address;
    }
}

(3)展示线性表中的数据元素,线性表具有物理相邻的特点,我们可用这一性质来查看线性表中的所有数据元素或数据项

void show(struct add* a)
{
    if (a->size == 0)
//当线性表没有任何数据元素时的情况
        cout << "当前没有任何记录" << endl;
    else
//当有元素时进行输出
    {
        for (int i = 0; i < a->size; i++)
//直接从物理上的开始位置起查找
        {
            cout << "姓名: " << a->arr[i].name << "   ";
            cout << "性别: " << (a->arr[i].sex == 1 ? "男" : "女") << "   ";
            cout << "年龄: " << a->arr[i].age << "   ";
            cout << "手机号: " << a->arr[i].phone << "   ";
            cout << "身份证号: " << a->arr[i].number << "   ";
            cout << "家庭地址: " << a->arr[i].address << endl;
        }
    }
}

(4)删除线性表中的数据元素,在这里我们要删除指定的数据项,将其对应的数据元素一起删除

可以先设置一个算法,先查找要删除的位置,然后进行删除

int foundperson(add* a,string name1)//查找指定人的位置
{
    for (int i = 0; i < a->size; i++)
    {
        if (a->arr[i].name == name1)
        {
            return i;
        }
    }
    return -1;
}
void deleteperson(add* a)
//要删除指定的人的姓名
{
    string name;
    int number;
    cin >> name;
    number = foundperson(a, name);
    if (number != -1)
    {
        for (int i = number; i < a->size; i++)
        {
            a->arr[i] = a->arr[i + 1];
        }
        a->size--;
        cout << "删除成功" << endl;
    }
    else
//当没有要删除指定的这个人时的情况
    {
        cout << "没有此人" << endl;
    }
}

(5)查找线性表中的数据元素,跟删除操作基本一致,先查找指定人的具体位置,然后根据这个线性表对应的物理位置直接查找

int foundperson(add* a,string name1)//查找指定人的位置,name1对应的是查找人的名字
{
    for (int i = 0; i < a->size; i++)
    {
        if (a->arr[i].name == name1)
        {
            return i;
        }
    }
    return -1;
}

void found(add* a)
{
    int i;
    string name;
    cin >> name;
    i = foundperson(a, name);
//指定查找人的位置
    if (i != -1)//查找人的基本信息
    {
        cout << "姓名: " << a->arr[i].name << "   ";
        cout << "性别: " << (a->arr[i].sex == 1 ? "男" : "女") << "   ";
        cout << "年龄: " << a->arr[i].age << "   ";
        cout << "手机号: " << a->arr[i].phone << "   ";
        cout << "身份证号: " << a->arr[i].number << "   ";
        cout << "家庭地址: " << a->arr[i].address << endl;
    }
    else
//当没有查到的情况
    {
        cout << "没有此人" << endl;
    }
}

(6)修改线性表中的数据元素,先找到数据项的位置,然后根据物理位置进行修改

int foundperson(add* a,string name1)//指定人的位置算法
{
    for (int i = 0; i < a->size; i++)
    {
        if (a->arr[i].name == name1)
        {
            return i;
        }
    }
    return -1;
}

void fix(add* a)
{
    int number;
    string name;
    cin >> name;
    number = foundperson(a, name);//指定人的位置
    if (number != -1)//进行修改
    { 
            //姓名
            cin >> a->arr[*p].name;
            //性别
            while (true)
            {
                int select;
                cin >> select;
                if (select == 1 || select == 2)
                {
                    if (select == 1)
                        a->arr[*p].sex = 1;
                    else
                        a->arr[*p].sex = 2;
                    break;
                }
            }
            //年龄
            cin >> a->arr[*p].age;
            //电话
            cin >> a->arr[*p].phone;
            //身份证号
            cin >> a->arr[*p].number;
            //地址
            cin >> a->arr[*p].address;
        }
    }
    else
    {
        cout << "没有此人" << endl;
    }
}

       由此可见,在基础操作中,查找,修改,删除三种方法基本思路一样,换种情其实也是一样的,你可以私下想象一下。

四,线性表中的链式表

        链式表其实就是我们之前学的链表。链表具有相连的逻辑关系,它可以表示各种复杂的非线性结构式。链表的逻辑结构要比顺序表的情况稍微复杂一点点。常见的链表形式有单向链表,双向链表,循环链表。

1,单向链表

        单向链表是最简单,最常用的链式结构之一,单链表中的每个结点只包含一个指针域,如图:

线性表的初级认识_第2张图片

        下面为单向链表的创建与输出:

#include
#include
typedef int type;
typedef struct h
{
    type a;
    struct h* next;
}Lnode;
Lnode* Link()
{
    type a, i = 0;
    Lnode* head = NULL, * p, * pa;
    head = p = (Lnode*)malloc(sizeof(Lnode));
    fscanf(stdin, "%d", &a);
    while (a != 0)
    {
        i++;
        if (i == 1)
        {
            head->a = a;//因为位顺序结构式,要先确定头节点
        }
        p->a = a;//当满足式子时加入,数据加入表中
        pa = (Lnode*)malloc(sizeof(Lnode));//建立结点
        p->next = pa;//建立连接
        p = pa;//顺序链接,建立相应的关系式子
        fscanf(stdin, "%d", &a);
    }
    p->next = NULL;
    return head;
}//以上已成功建立
type main()
{
    Lnode * t;
    for (t = Link(); t->next != NULL; t = t->next)
    {
        fprintf(stdout, "%d ", t->a);
    }
    return 0;
}
 

2,双向链表

        单项链表中的每个结点只能指向前面的结点,如果再加上一个指针域指向后面的结点,这种链表称为双向链表。如图:

线性表的初级认识_第3张图片

下面为双向链表的创建与双向输出

#include"linkc.h"//自己写的必要头文件
struct pa
{
    type a;
    link* next1, * next2;//next1指向前趋,next2指向后继
};
int main()
{
    int n = 0;
    link* p, * pp, *head;
    p = head = (link*)malloc(sizeof(link));
    scanf("%d", &p->a);
    while (p->a)
    {
        pp=(link*)malloc(sizeof(link));
        scanf("%d", &pp->a);
        p->next1 = pp;
        pp->next2 = p;//逆向建立连接,建立双向
        p = pp;
    }
    p->next1 = 0;//正向的末尾
    head->next2 = 0;//逆向的末尾
    //双向链表正向输出
    for (pp = head; pp->next1; pp = pp->next1)
    {
        printf("%d ", pp->a);
        Sleep(500);
    }
    printf("\n");
    //双向链表的逆向输出
    for (pp = p; pp->next2; pp = pp->next2)
    {
        printf("%d ", pp->a);
        Sleep(500);
    }
    return 0;
}
 

3,循环链表

循环链表是一种首尾相接的链表,具有无限循环结构。在单链表中,如果最后一个结点的指针域直接指向头节点,这就变成了循环链表。循环链表的结构式如图所示:

线性表的初级认识_第4张图片

下面是循环链表的创建和输出的代码演示:

#include"linkc.h"//头文件,里面我们设置的一些简单的基础操作
struct pa
{
    type a;
    link* next;
};
int main()
{
    link* p, * head, * pp;
    p = head = (link*)malloc(sizeof(link));
    scanf("%d", &p->a);
    while (p->a)//终止条件为0
    {
        pp = (link*)malloc(sizeof(link));
        scanf("%d", &pp->a);
        p->next = pp;
        p = pp;
    }
    p->next = head;//将最后结点指向头节点
    for (pp = head;; pp = pp->next)//查看循环链表,不用设置条件
    {
        printf("%d\n", pp->a);
        Sleep(500);//控制输出时间,因为循环链表是无限循环
    }
    return 0;
}
 

总:单向链表,双向链表,循环链表都是基础的链式结构,更为复杂的如双向循环链表,双向带头循环链表等,但需注意的是,虽然链式结构复杂多样,基本的运算规律都是一致的思想,只要在形式上稍微改动即可,初级的线性表一共大约也就这么多,顺序表比较简单,没有涉及复杂的结构和逻辑思想,至于跟为复杂的链式结构式以及线性表的使用逻辑和注意事项,后面的深入文章会给大家做出详细的讲解。

你可能感兴趣的:(算法)