顺序表基础

定长顺序表(线性表):

线性表的定义:

存在唯一的一个被称为“第一个”的数据元素;

存在唯一的一个被称为“最后一个”的数据元素;

除第一个之外,集合中的每一个数据元素都只有一个前驱;

除最后一个之外,集合中的每一个数据元素都只有一个后继;

线性表是最简单最常用的一种线性表。

线性表分为顺序表和链表。

顺序表又分为定长顺序表和不定长顺序表。

线性表的顺序表,顺序表的设计思想:

typedef struct SqList

{

        int elem[10];

        int length;

}SqList;

结构示意图如下:

顺序表基础_第1张图片

实现顺序表的操作

//不定长顺序表的实现

#include "sqlist.h"
#include
#include

//初始化
void InitSqlist(PSQList ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        return;

    ps->length = 0;
}

//判满

static bool IsFul(PSQList ps)
{
    return ps->length == 10;
}

//插入数据,在ps顺序表的pos位置插入val;
bool Insert(PSQList ps, int pos, int val)
{
    assert(ps != NULL);
    if (ps == NULL)
        return false;

    if (pos<0 || pos>ps->length || IsFul(ps))
    {
        return false;
    }
    //把数据移动到后面
    for (int i = ps->length - 1; i >= pos; i--)
    {
        ps->elem[i + 1] = ps->elem[i];
    }
    //插入数据
    ps->elem[pos] = val;
    //有效数据个数++;
    ps->length++;    
    return true;
}

//判空
bool IsEmpty(PSQList ps)
{
    return ps->length == 0;
}

//在ps中查找第一个key值,找到返回下标,没有找到返回-1;
int Search(PSQList ps, int key)
{
    for (int i = 0; i < ps->length; i++)
    {
        if (key == ps->elem[i])
            return i;
    }
    return -1;
}

//删除pos位置的值
bool DelPos(PSQList ps, int pos)
{
    assert(ps != NULL);
    if (ps == NULL)
        return false;

    if (pos<0 || pos>=ps->length)
    {
        return false;
    }
    //将后面的数据前移
    for (int i = pos; i < ps->length - 1; i++)
    {
        ps->elem[i] = ps->elem[i + 1];
    }
    //有效数据个数--;
    ps->length--;
    return true;
}

//删除第一个val的值
bool DelVal(PSQList ps, int val)
{
    int  i = Search(ps, val);
    if (i < 0)
        return false;

    return DelPos(ps, i);
}

//返回key的前驱下标,如果不存在返回-1;
int GetPrio(PSQList ps, int key)
{
    int i = Search(ps, key);
    if (i <= 0)//注意头没有前驱
        return -1;

    return i - 1;
}

//返回key的后继下标,如果不存在返回-1;
int GetNext(PSQList ps, int key)
{
    int i = Search(ps, key);
    if (i < 0 || i == ps->length - 1)//注意,尾没有后继
        return -1;

    return i + 1;
}

//输出
void Show(PSQList ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        return;

    for (int i = 0; i < ps->length; i++)
    {
        printf("%d  ", ps->elem[i]);
    }
    printf("\n");
}

//清空数据
void Clear(PSQList ps)
{
    ps->length = 0;
}

//销毁整个内存
void Destroy(PSQList ps)
{
    Clear(ps);
}

不定长顺序表:

        不定长顺序表的结构:

                typedef struct DSQList{

                        int *elem;//动态内存的地址

                        int length;//有效数据的个数

                        int listsize;//总容量

                }DSQList,*DPSQList;

                 不定长顺序表相对于定长顺序表多了一个可以扩容的部分;为了实现扩容,我们必须在定长顺序表的基础上加上一个总容量(否则我们实现不了顺序表的判满);结构示意图如下

顺序表基础_第2张图片

 不定长顺序表的视线(重点)

#include

#include

#include

#define INIT_SIZE 10

//初始化

void InitSqlist(DPSQList ps)

{

        assert(ps!=NULL);

        if(ps==NULL)

                return;

        

        ps->elem = (int*)malloc(INIT_SIZE*sizeof(int));

        ps->length = 0;

        ps->listsize = INIT_SIZE;

}

//判满

static bool IsFull(DPSQList ps)

{

        return ps->length == ps->listsize;

}

//扩容

static bool Inc(DPSQList ps)

{

        ps->elem = (int*)realloc(ps->elem,ps->listsize*2*sizeof(int));

        assert(ps->elem!=NULL);

        ps->listsize*=2;

        return true;

}

//插入数据,在ps表中pos位置插入val

bool Insert(DPSQList ps,int pos,int val)

{

        assert(ps!=NULL);

        if(ps==NULL)

                return false;

        if(pos<0||pos>ps->length)

        {

                return false;

        }

        if(IsFull(ps))

        {

                Inc(ps);

        }

        //将数据后移

        for(int i = ps->length-1;i>=pos;i--)

        {

                ps->elem[i+1] = ps->elem[i];

        }

        //插入新数据

        ps->elem[pos] = val;

        //有效数据个数++

        ps->length++;

        return true;

}

//判空

bool IsEmpty(DPSQList ps)

{

        return ps->length==0;

}

        

//在ps表中查找第一个key值,找到返回下表,没找到返回-1

int Search(DPSQList ps,int key)

{        

        assert(ps!=NULL);

        if(ps==NULL)

                return -1;

        for(int i=0;ilength;i++)

        {

                if(ps->elem[i]==key)

                        return i;

        }

        return -1;

}

//删除pos位置的值

bool DelPos(DPSQList ps,int pos)

{

        assert(ps!=NULL);

        if(ps==NULL)

                return false;

        if(pos<0||pos>ps->length)

                return false;

        //删除pos位置

        for(int i = pos;ilength;i++)

        {

                ps->elem[i] = ps->elem[i+1];

        }

        //有效位置个数--

        ps->length--;

        return true;

}

/

//删除第一个val的值
bool DelVal(DPSQList ps, int val)
{
    int i = Search(ps, val);
    if (i < 0)
        return false;

    return DelPos(ps, i);
}

//返回key的前驱下标,如果不存在返回-1;
int GetPrio(DPSQList ps, int key)
{
    int i = Search(ps, key);
    if (i <= 0)
        return -1;

    return i - 1;
}

//返回key的后继下标,如果不存在返回-1;
int GetNext(DPSQList ps, int key)
{
    int i = Search(ps, key);
    if (i < 0 || i == ps->length - 1)
        return -1;

    return i + 1;
}

//输出
void Show(DPSQList ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        return;
    for (int i = 0; i < ps->length; i++)
    {
        printf("%d  ", ps->elem[i]);
    }
    printf("\n");
}

//清空数据
void Clear(DPSQList ps)
{
    ps->length=0;
}

/销毁整个内存
void Destroy(DPSQList ps)
{
    free(ps->elem);
    ps->elem = NULL;
    ps->length = 0;
    ps->listsize = 0;
    ps = NULL;//无效的代码
}

以上为不定长顺序表的结构以及主要的作用

顺序表的总结:

顺序表的特点:
1.插入数据的时间复杂度是O(n),如果是尾插时间复杂度是O(1);
2.删除数据的时间复杂度是O(n),如果是尾删时间复杂度是O(1);
3.通过下标访问数据时间复杂度是O(1);

顺序表逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素;
存储密度大(高),每个结点只存储数据元素(对比链表);
随机访问:顺序表是一种支持随机存取的存储结构,根据起始地址加上元素的序号,可以在O(1)时间内找到指定的元素,这就是随机存取的概念;

顺序表的一些其他函数

(1)设顺序表ps中的数据元素递增有序。试写一算法,将x插入到顺序表的适当位置上,以保持该表的有序性.
    

//有序顺序表插入x;
bool InsertX(DPSQList ps, int x)
{
    assert(ps != NULL);
    if (ps == NULL)
    {
        return false;
    }
    int i;
    for (i = 0; i < ps->length; i++)
    {
        if (ps->elem[i] > x)
        {
            break;
        }
    }
    return Insert(ps,i,x);
}

(2)设 ListA=(a1,....am)和ListB=(b1,...bn)均为顺序表。试写一个比较ListA,ListB大小的算法,依次比较ListA,ListB元素的值,如果一样则继续比较,如果不一样则比较完成.
//顺序表比较大小
int  DSqlistCmp(DPSQList listA, DPSQList listB)
{
    int i;
    for ( i = 0; i < listA->length && listB->length; i++)
    {
        if (listA->elem[i] != listB->elem[i])
        {
            return  listA->elem[i] - listB->elem[i];
        }
    }
    return listA->length - listB->length;
}

(3)试写一算法,实现顺序表的就地逆置,即利用原表的存储空间将线性表(a1,...an)  逆置为(an,...a1) 
 

//逆置顺序表
void Reverse(DPSQList ps)
{
    int tmp;
    for (int i = 0, j = ps->length - 1; i < j; i++, j--)
    {
        tmp = ps->elem[i];
        ps->elem[i] = ps->elem[j];
        ps->elem[j] = tmp;
    }
}

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