数据结构之线性表(一)

线性表的顺序存储结构——顺序表

线性表是具有享用特性的数据元素的一个有限序列,线性表的顺序存储结构简称为顺序表。

线性表

顺序表

顺序表的数据类型

typedef struct
{
    ElemType data[MaxSize];
    int length;
}SqList;

typedef简单用法

typedef 声明,简称 typedef,为现有类型创建一个新的名字。比如人们常常使用 typedef 来编写更美观和可读的代码。所谓美观,意指 typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。 在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。

typedef的使用方法如下:

typedef existing_type new_type_name ;

注意:typedef 并不创建新的类型。它仅仅为现有类型添加一个同义字。

关于引用的简单说明

向函数传递参数的引用调用方法,把引用的地址复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
按引用传递值,参数引用被传递给函数,就像传递其他值给函数一样。因此相应地,在下面的函数 swap() 中,您需要声明函数参数为引用类型,该函数用于交换参数所指向的两个整数变量的值。

// 函数定义
void swap(int &x, int &y)
{
   int temp;
   temp = x; /* 保存地址 x 的值 */
   x = y;    /* 把 y 赋值给 x */
   y = temp; /* 把 x 赋值给 y  */

   return;
}

引用的优点:比起传指针,传引用更加方便; 比起传值,传引用速度更快,节省空间。但是引用一旦定义就不能再引用其他变量,直至该引用灭亡。

线性表代码实现:

#include <iostream>
#include <cstdio>
#include <cstdlib>

#ifdef WIN32
#include <malloc.h>
#else
#include <sys/malloc.h>
#endif

using namespace std;

const int MaxSize = 50;
typedef int ElemType;

typedef struct
{
    ElemType data[MaxSize];
    int length;
}SqList;

//SqList *L 为指针变量, SqList & 为引用, SqList *&为指针的引用
//注意没有引用的指针,因为引用本身不是变量,不在内存中占有空间
void CreateList(SqList *&L, ElemType a[], int n);
void InitList(SqList *&L);
void DestroyList(SqList *&L);
bool ListEmpty(SqList *L);
int ListLength(SqList *L);
void DispList(SqList *L);
bool GetElem(SqList *L, int i, ElemType &e);
int LocateElem(SqList *L, ElemType e);
bool ListInsert(SqList *&L, int i, ElemType e);
bool ListDelete(SqList *&L, int i, ElemType &e);
void Delnodel(SqList *&L, ElemType x);
void Partition(SqList *&L);
void QuickSort(SqList *&L, int left, int right);
void Change(ElemType &a, ElemType &b);

int main(void)
{
    SqList *L;
    /*
    int a[10] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
    CreateList(L, a, 10);
    DispList(L);
    ListInsert(L, 3, 10);
    DispList(L);
    ElemType e;
    ListDelete(L, 2, e);
    DispList(L);
    delnodel(L, 10);
    DispList(L);
     */
    int a[10] = {5, 1, 3, 7, 9, 2, 4, 6, 8, 10};
    CreateList(L, a, 10);
    DispList(L);
    //Partition(L);
    QuickSort(L, 0, 10);
    DispList(L);

    return 0;
}

//建立顺序表 时间复杂度O(N)
void CreateList(SqList *&L, ElemType a[], int n)
{
    L = (SqList *)malloc(sizeof(SqList));   //分配存储线性表的空间
    for (int i = 0; i < n; i++)
        L->data[i] = a[i];                  //将数组a中的元素存放到L中
    L->length = n;                          //设置线性表的长度
}

//初始化线性表 时间复杂度O(1)
void InitList(SqList *&L)
{
    L = (SqList *)malloc(sizeof(SqList));   //分配存储线性表的空间
    L->length = 0;                          //置空线性表的长度为0
}

//销毁线性表 时间复杂度O(1)
void DestroyList(SqList *&L)
{
    free(L);        //释放L所指的顺序表空间
    L = NULL;       //将L指向NULL(保障安全)
}

//求线性表的长度 时间复杂度O(1)
int ListLength(SqList *L)
{
    return (L->length);
}

//判断线性表是否为空表 时间复杂度O(1)
bool ListEmpty(SqList *L)
{
    return (L->length == 0);
}

//输出线性表 时间复杂度O(N)
void DispList(SqList *L)
{
    if (ListEmpty(L))                   //判断线性表是否为空,为空则抛出提示信息
    {
        printf("线性表为空表!\n");
        return;
    }
    for (int i = 0; i < L->length; i++) //线性表若非空,则输出线性表的元素
        printf("%d ", L->data[i]);
    printf("\n");
}

//求线性表中的某个数据元素值(i为逻辑索引) 时间复杂度O(1)
bool GetElem(SqList *L, int i, ElemType &e)
{
    if (i < 1 || i > L->length)     //输入的索引有误
        return false;
    e = L->data[i-1];               //向引用e返回元素值
    return true;
}

//按元素值查找(返回逻辑索引) 时间复杂度O(N)
int LocateElem(SqList *L, ElemType e)
{
    int i;
    for (i = 0; i < L->length; i++)
    {
        if (e == L->data[i])        //若找到该元素则退出寻找
            break;
    }
    if (i == L->length)             //未找到
        return -1;
    else
        return i+1;
}

//插入数据元素 时间复杂度O(N)
bool ListInsert(SqList *&L, int i, ElemType e)
{
    if (i < 1 || i > L->length+1)   //输入的索引有误
        return false;
    i--;
    for (int j = L->length; j > i; j--) //将data[i]及后面的元素后移一个位置
        L->data[j] = L->data[j-1];
    L->data[i] = e;                 //将该元素插入
    L->length++;                    //线性表长度加一

    return true;
}

//删除数据元素 时间复杂度O(N)
bool ListDelete(SqList *&L, int i, ElemType &e)
{
    if (i < 1 || i > L->length)     //输入的索引有误
        return false;
    i--;
    e = L->data[i];                 //向引用e返回所删除的元素值
    for (int j = i; j < L->length-1; j++)   //将data[i]之后的元素前移一个位置
        L->data[j] = L->data[j+1];
    L->length--;                    //线性表长度减一

    return true;
}

//删除线性表中所有值为x的元素 时间复杂度O(N)
void Delnodel(SqList *&L, ElemType x)
{
    int k = 0;
    for (int i = 0; i < L->length; i++)
    {
        if (L->data[i] != x)        //若当前元素不为x,则将其插入到L中
        {
            L->data[k] = L->data[i];
            k++;
        }
    }
    L->length = k;
}

//使用引用交换两个变量的值 时间复杂度O(1)
void Change(ElemType &a, ElemType &b)
{
    //三变量法
    ElemType t;
    t = a;
    a = b;
    b = t;
}

//以第一个元素为分界线,将表中所有小于等于它的元素移到该基准的前端,大于的则移动到后面
//时间复杂度O(N)
void Partition(SqList *&L)
{
    int i = 0, j = L->length-1;
    ElemType pivot = L->data[0];
    while (i < j)
    {
        while (i < j && L->data[j]>pivot)
            j--;
        while (i < j && L->data[i]<=pivot)
            i++;
        if (i < j)
            Change(L->data[i], L->data[j]);
    }
    Change(L->data[0], L->data[i]);
}

void QuickSort(SqList *&L, int left, int right)
{
    //如果left不小于right,需要排序的部分只有一个元素,退出排序
    if (left >= right)
        return;

    int i, j;
    ElemType pivot = L->data[left]; //设置左边的元素为基准点
    i = left;
    j = right;
    while (i < j)
    {
        //要让右边的向左移动,请想一想为什么
        //j向左移,找到一个比p小的元素
        while (i < j && L->data[j] >= pivot)
            j--;
        //i向右移,找到一个比p大的元素
        while (i < j && L->data[i] <= pivot)
            i++;
        //i和j交换
        if (i < j)
            Change(L->data[i], L->data[j]);
    }
    L->data[left] = L->data[i];
    L->data[i] = pivot;
    //对序列中,i左边的元素实施快速排序
    QuickSort(L, left, i-1);
    //对序列中,i右边的元素实施快速排序
    QuickSort(L, i+1, right);
}

顺序表的插入、删除、快排需要自己在纸上模拟一下,以后的链表、栈等数据结构都要养成模拟的好习惯o(∩_∩)o ~

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值