什么是顺序表?

顺序表是线性表的一种,以数组的方式表示。即内存连续且存储的数据元素类型相同

顺序表可以看做一个数组,只是我们一开始学数组的时候数组中存储的是简单的数据类型,如int、char等,现在顺序表中存数的是一个结构体数据。结构体数据又是由多个以简单数据类型为基础的数据项组成的。当定义了一个该数据结构体变量时,该变量就是一个数据元素,结构体内的数据项就是该数据元素的基本属性。当有多个这种数据元素时,可以将它们存放在一个结构体数组中,这时这个结构体数组就是一个数据对象

从内存上去看,每一个数据项的空间分配都是线性的,几块数据项又组成了一个数据元素。所以可以发现,对结构体的访问和操作都可以用指针来实现

顺序表 vs 单链表

顺序表结构体声明

typedef struct sequenList{//数据
    //数据项
    INT data[N];
    int last;//数组data的最后一个数据的下标
    int lenth;//数组的大小
}LIST, *SLIST;

typedef重命名:将struct sequenList重命名为LIST,将LIST*重命名为SLIST

顺序表的操作

基本操作:创建、插入、删除、遍历(打印)、查找、修改、排序、合并等

创建一个顺序表

LIST *creat()
{
    LIST *list = (LIST *)malloc(sizeof(LIST));
    memset(list->data,0,sizeof(INT)*N);
    list->last = -1;
    list->lenth = 0;
    return list;
}

创建思路:

  1. 动态内存分配
  2. 数据项初始化
  3. 返回新开辟空间的首地址

顺序表判空

int isEnpty(LIST *list)
{
    return list->lenth==0 ? 1 : 0;
}

根据数据项的属性来判断

顺序表判满

int isFull(LIST *list)
{
    if(list->lenth == N)
        return 1;
    else
        return 0;
}

根据顺序表长度是否达到分配空间容量极限来判断

尾插法

void tailInsert(LIST *list,INT val)
{
    list->last++;
    list->data[list->last] = val;
    list->lenth++;
}

相当于给数组中加入新的值。先要操作下标,后赋值

在给定位置插入数据元素

void insert(LIST *list,int position,INT val)
{
    int i;
    if(isFull(list))
        printf("表满\n");
    if(position<0 && position>list->last)
    {
        printf("位置不合法\n");
    }
    else{
        for(i=list->lenth;i>position;i--)
        {
            list->data[i] = list->data[i-1];
        }
        list->data[position] = val;
        list->lenth++;
        list->last++;
    }
}

1、判断表是否还有空间可以插入

2、判断给的位置是否可以插入

3、插入操作:从给定位置开始,数据依次往后移一位,腾出给定位置后插入,并修改相应数据项改变量

从尾部删除一个元素

void deletList(LIST *list)
{
    if(isEnpty(list))
        printf("空表\n");
    else
    {
        INT *p = &(list->data[0]);
        bzero(p+list->last,sizeof(INT));
        list->last--;
        list->lenth--;
    }
}

若表不为空,则用到了清空bzero函数

按照位置删除数据

void deletBypos(LIST *list,int position)
{
    int i;
    if(isEnpty(list))
        printf("表空");
    if(position<=0 && position>list->last)
        printf("位置不合法");
    else{
        for(i=position;i<list->last;i++)
        {
            list->data[i] = list->data[i+1];
        }
        if(position == list->last)
            deletList(list);
        list->last--;
        list->lenth--;
    }
}

1、判断表空否和位置合法否

2、采用从该位置开始,后一项依次赋值覆盖前一项操作,并删除最后一个数据元素,最后修改相应数据项

删除表中有重复的数据,只留一个

void deletRepetitionData(LIST *list,INT data)
{
    int i,j;
    if(isEnpty(list))
        printf("表空\n");
    else{
        for(i=0;i<list->last;i++)
        {
            for(j=i+1;j<=list->last;j++)
            {
                if(list->data[i]==list->data[j])
                    deletBypos(list,j);
                //printf("i=%d j=%d\n",i,j);//test
                //printList(list);//test
            }
            if(list->data[i] == list->data[--j])
                deletList(list);
        }
    }
}

1、检查表空否

2、遍历查找,先锁定一个数据元素,再遍历之后的数据元素是否有和锁定的数据元素重复,若重复则根据下标删除重复的数据元素

3、若是照上述编写程序,基本上能实现删除表中有重复的数据,但存在一个bug,如果重复的数据是连续2个以上且在表的末尾,则无法全部删除。结果如下:

60 60 30 60 80 60 60
60 30 80 60

test:
60 60 30 60 80 60 60
i=0 j=1
60 30 60 80 60 60
i=0 j=2
60 30 80 60 60
i=0 j=3
60 30 80 60
i=1 j=2
60 30 80 60
i=1 j=3
60 30 80 60
i=2 j=3
60 30 80 60

测试发现,第9~12行,由于删除重复元素后该元素后面的待遍历元素会往前移一位,而 j++又让待遍历元素下标往后移了一位,若遇上述情况,则导致恰巧错失比较了一个重复元素。因此在每次删除完重复数据后,将 j 回置1位并判断此时的元素是否与锁定元素相同,若相同则立即删除它。这只是一种情况,实际上还有多种,每种解决的方法又不同。。。

4、此问题有待解决。

遍历(打印)

void printList(LIST *list)
{
    int i;
    for(i=0;i<=list->last;i++)
        printf("%d ",list->data[i]);
    putchar(10);
}

从第一项开始循序往后访问直到最后一项

根据给定数据直接修改更新数据

void updataByData(LIST *list,INT data,INT val)
{
    int i;
    for(i=0;i<=list->last;i++)
    {
        if(data == list->data[i])
            list->data[i] = val;
    }
}

遍历寻找需要修改的数据并赋值覆盖

根据给定下标位置来修改更新数据

void updataByIndex(LIST *list,int position,INT val)
{
    if(position>=0 && position<=list->last)
        list->data[position] = val;
}

先判断给出位置是否合法,若合法直接通过下标修改数据

查找表中是否有某一数据

int referByDate(LIST *list,INT data)
{
    int i;
    for(i=0;i<=list->last;i++)
    {
        if(list->data[i] == data)
            return 1;
    }
    return 0;
}

遍历的过程,加入判断条件

查找表中某一数据的位置

void findPos(LIST *list,INT data)
{
    int i,flag = 1;
    for(i=0;i<=list->last;i++)
    {
        if(data == list->data[i])
        {
            printf("%d ",i);
            flag = 0;
        }
    }
    if(flag)printf("%d",-1);
    putchar(10);
}

遍历的过程,加入判断条件

合并两个顺序表

void combineList(LIST *li1,LIST *li2)
{
    int i;
    for(i=0; i<=li2->last; i++)
    {
        if(!referByDate(li1,li2->data[i]))
            tailInsert(li1,li2->data[i]);
    }
}

从表2中将表1中没有的数据插入到表1中

遍历表2,判断遍历的每一个数据在表1中是否存在,若不存在,则在表1中尾部插入

对表中数据顺序排序

void sortList(LIST *list)
{
    int i,j,flag,temp;
    for(i=0;i<list->last;i++)
    {
        flag = i;
        for(j=i+1;j<=list->last;j++)
        {
            if(list->data[j] < list->data[flag])
                flag = j;
        }
        temp = list->data[i];
        list->data[i] = list->data[flag];
        list->data[flag] = temp;
    }
}

选择排序

示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEST 1
#define N 100

typedef int INT;
typedef struct sequenList{//数据
    //数据项
    INT data[N];
    int last;//数组data的最后一个数据的下标
    int lenth;//数组的大小
}LIST;

LIST *creat();
int isEnpty(LIST *list);
int isFull(LIST *list);
void tailInsert(LIST *list,INT val);
void insert(LIST *list,int position,INT val);
void printList(LIST *list);
void deletList(LIST *list);
void updataByData(LIST *list,INT data,INT val);
void updataByIndex(LIST *list,int position,INT val);
void referByIndex(LIST *list,INT data);
void findPos(LIST *list,INT data);
void deletBypos(LIST *list,int position);
void deletRepetitionData(LIST *list,INT data);
void combineList(LIST *li1,LIST *li2);
void sortList(LIST *list);

int main(int argc, const char *argv[])
{
    LIST *list = creat();//list:数据元素
    LIST *list1 = creat();
#if TEST
    printf("%d\n",sizeof(LIST));
    tailInsert(list,60);
    tailInsert(list,20);
    tailInsert(list,30);
    printList(list);//60 20 30
    deletList(list);
    printList(list);//60 20
    tailInsert(list,30);
    tailInsert(list,20);
    printList(list);//60 20 30 20
    updataByData(list,20,60);
    tailInsert(list,60);
    printList(list);//60 60 30 60 60
    //updataByIndex(list,2,60);
    updataByIndex(list,2,80);
    printList(list);//60 60 80 60 60
    findPos(list,60);//0  1    3  4
    insert(list,1,30);
    printList(list);//60 30 60 80 60 60
    tailInsert(list,70);
    printList(list);//60 30 60 80 60 60 70
    deletBypos(list,6);
    printList(list);//60 30 60 80 60
    insert(list,1,60);
    printList(list);//60 60 30 60 80 60
    tailInsert(list,60);
    printList(list);//60 60 30 60 80 60
    deletRepetitionData(list,60);
    printList(list);

    tailInsert(list1,99);
    tailInsert(list1,88);
    tailInsert(list1,80);
    tailInsert(list1,22);
    tailInsert(list1,66);
    tailInsert(list1,50);
    printf("list : ");
    printList(list);
    printf("list1: ");
    printList(list1);
    combineList(list,list1);
    printf("combi: ");
    printList(list);
    printf("sort : ");
    sortList(list);
    printList(list);

#else

#endif
    return 0;
}
//创建一个顺序表
LIST *creat()
{
    LIST *list = (LIST *)malloc(sizeof(LIST));
    memset(list->data,0,sizeof(INT)*N);
    list->last = -1;
    list->lenth = 0;
    return list;
}
//顺序表判空
int isEnpty(LIST *list)
{
    return list->lenth==0 ? 1 : 0;
}
//顺序表判满
int isFull(LIST *list)
{
    if(list->lenth == N)
        return 1;
    else
        return 0;
}
//尾插法
void tailInsert(LIST *list,INT val)
{
    list->last++;
    list->data[list->last] = val;
    list->lenth++;
}
//在给定位置插入数据元素
void insert(LIST *list,int position,INT val)
{
    int i;
    if(isFull(list))
        printf("表满\n");
    if(position<0 && position>list->last)
    {
        printf("位置不合法\n");
    }
    else{
        for(i=list->lenth;i>position;i--)
        {
            list->data[i] = list->data[i-1];
        }
        list->data[position] = val;
        list->lenth++;
        list->last++;
    }
}
//遍历
void printList(LIST *list)
{
    int i;
    for(i=0;i<=list->last;i++)
        printf("%d ",list->data[i]);
    putchar(10);
}
//从尾部删除一个元素
void deletList(LIST *list)
{
    if(isEnpty(list))
        printf("空表\n");
    else
    {
        INT *p = &(list->data[0]);
        bzero(p+list->last,sizeof(INT));
        list->last--;
        list->lenth--;
    }
}
//根据给定数据直接修改更新
void updataByData(LIST *list,INT data,INT val)
{
    int i;
    for(i=0;i<=list->last;i++)
    {
        if(data == list->data[i])
            list->data[i] = val;
    }
}
//查找表中是否有某一数据
int referByDate(LIST *list,INT data)
{
    int i;
    for(i=0;i<=list->last;i++)
    {
        if(list->data[i] == data)
            return 1;
    }
    return 0;
}
//根据给定下标位置来修改更新数据
void updataByIndex(LIST *list,int position,INT val)
{
    if(position>=0 && position<=list->last)
        list->data[position] = val;
}
//查找表中某一数据的位置
void findPos(LIST *list,INT data)
{
    int i,flag = 1;
    for(i=0;i<=list->last;i++)
    {
        if(data == list->data[i])
        {
            printf("%d ",i);
            flag = 0;
        }
    }
    if(flag)printf("%d",-1);
    putchar(10);
}
//按照位置删除数据
void deletBypos(LIST *list,int position)
{
    int i;
    if(isEnpty(list))
        printf("表空");
    if(position<=0 && position>list->last)
        printf("位置不合法");
    else{
        for(i=position;i<list->last;i++)
        {
            list->data[i] = list->data[i+1];
        }
        if(position == list->last)
            deletList(list);
        list->last--;
        list->lenth--;
    }
}
//删除表中有重复的数据,只留一个
void deletRepetitionData(LIST *list,INT data)
{
    int i,j;
    if(isEnpty(list))
        printf("表空\n");
    else{
        for(i=0;i<list->last;i++)
        {
            for(j=i+1;j<=list->last;j++)
            {
                if(list->data[i]==list->data[j])
                    deletBypos(list,j);
                //printf("i=%d j=%d\n",i,j);//test
                //printList(list);//test
            }
            if(list->data[i] == list->data[--j])
                //deletBypos(list,j);
                deletList(list);
        }
    }
}
//将两个表合并
void combineList(LIST *li1,LIST *li2)
{
    int i;
    for(i=0; i<=li2->last; i++)
    {
        if(!referByDate(li1,li2->data[i]))
            tailInsert(li1,li2->data[i]);
    }
}
//对表中数据顺序排序
void sortList(LIST *list)
{
    int i,j,flag,temp;
    for(i=0;i<list->last;i++)
    {
        flag = i;
        for(j=i+1;j<=list->last;j++)
        {
            if(list->data[j] < list->data[flag])
                flag = j;
        }
        temp = list->data[i];
        list->data[i] = list->data[flag];
        list->data[flag] = temp;
    }
}

结果

408
60 20 30
60 20
60 20 30 20
60 60 30 60 60
60 60 80 60 60
0 1 3 4
60 30 60 80 60 60
60 30 60 80 60 60 70
60 30 60 80 60
60 60 30 60 80 60
60 60 30 60 80 60 60
60 30 80
list : 60 30 80
list1: 99 88 80 22 66 50
combi: 60 30 80 99 88 22 66 50
sort : 22 30 50 60 66 80 88 99
Last modification:2021 年 03 月 26 日 11 : 05 : 53