C - 数据结构 - 线性表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/grassroots2011/article/details/52644131

其实目前网上的各种的都有,只是每个人阅读带给自己的感受是不一样的,只有自己亲手体验过才叫真的体会过,阅读代码的确会给人很多启发,抱着一种学习的心态看待代码,开始正题

线性结构的特点:在数据元素的非空有限集中
1. 存在唯一的一个被称做“第一个”的数据元素
2. 存在唯一的一个被称做“最后一个”的数据元素
3. 除第一个之外,集合中的每个数据元素均只有一个前驱
4. 除最后一个之外,集合中每个元素均只有一个后续

线性表的类型定义

linear list 是最常用且最简单的一种数据结构。
一个线性表示n个数据元素的有限序列。

简单来说就是一条直线型的数据结构:
。——。——。——。——。
每个节点都是一个数据元素,可以是一个变量,也可以是一个结构体,但是他们之间存在直线型的关系。

线性表其实是一种数据结构集合,这种数据结构集合包含了许多以线性的数据结构,列入顺序表,链表,队列,堆栈等;

线性表的顺序表示和实现

线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素

  1. 定义一个结构体单元
  2. 包含数据元素的地址(根据连续的数据元素地址进行插入以及删除数据操作)
  3. 当前分配的内存容量(数据元素地址用满时,利用它进行判断,增加内存)
  4. 当前的长度(记录有多少个数据元素,使我们可以对数据元素的操作更加方便)
// 线性表的动态分配顺序存储结构
#define LIST_INIT_SIZE 100 // 线性表存储空间的初始分配量
#define LISTINCREMENT 10  // 线性表存储空间的分配增量
typedef struct {
    ElemType *elem; // 数据元素的地址
    int   length; // 当前长度
    int   listsize;//当前分配的存储容量(以sizeof(ElemType)为单位)
}

线性表顺序表示操作实例代码

/***
 *Arrlist.h
 *  Copyright © 2016年 liuxinming. All rights reserved.
 *Purpose:
 *   线性表顺序存储结构的创建、数据插入、数据获取、获取长度、删除数据、清空数据、销毁顺序存储结构方法的实现
 ***/
#include <stdio.h>
#include <stdlib.h>
#include "string.h"

#define LIST_INIT_SIZE 100 // 线性表存储空间的初始分配量
#define LISTINCREMENT 10   // 线性表存储空间的分配增量

// 函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK  1
#define ERROR 0
#define INFEASIBLE -1
#define OVERLOW -2

// Status 是函数的类型, 其值是函数结果状态代码
typedef int Status;
typedef int ElemType;

// -----线性表的动态分配顺序存储结构-----
typedef struct
{
    ElemType * elem; // 存储空间基址
    int length;      // 当前长度
    int listsize;    // 当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList;

// 操作结果:构造一个空的线性表L
Status InitList(SqList *L){
    // 为结构体中的存储空间分配内存
    L->elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if(! L->elem) exit(OVERLOW); // 存储分配失败

    L->length = 0; // 空表长度为0
    L->listsize = LIST_INIT_SIZE; // 初始存储容量
    return OK;
}// InitList_sq

// 初始条件:线性表L已存在
// 操作结果:销毁线性表L
Status DestroyList(SqList *L){
    // 判断指针是否为空
    if (L == NULL) {
        return ERROR;
    }
    // 释放calloc, malloc, realloc动态分配的空间
    free(L->elem);
    L->elem = NULL;
    L->length = 0;
    L->listsize = 0;
    return OK;
}// DestroyList

// 初始条件:线性表L已存在
// 操作结果:将L重置为空表。
Status ClearList(SqList *L){
    // 判断指针是否为空
    if (L == NULL) {
        return ERROR;
    }

    L->length = 0;
    return OK;
}// ClearList

// 初始条件:线性表L已存在
// 操作结果:若L为空表,则返回TRUE,否则返回FALSE
Status ListEmpty(SqList L){
    if (L.length == 0)
        return TRUE;
    else
        return FALSE;
}// ListEmpty

// 初始条件:线性表L已存在
// 操作结果:返回L中数据元素个数
Status ListLength(SqList L){
    return L.length;
}

// 初始条件:线性表L已存在, 1<=i<=ListLength(L)
// 操作结果:用e返回L中第i个数据元素的值
Status GetElem(SqList L, int i, ElemType *e){
    if (i<1 || i>L.length)
        exit(ERROR);
    *e =* (L.elem+i-1);
    return OK;
}

// 初始条件:线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0)。
// 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。若这样的数据元素不存在,则返回值为0.
Status LocateElem(SqList L, ElemType e, Status(*compare)(ElemType,ElemType)){
    ElemType *p;
    int i = 1; // i的初值为第一个元素的位序
    p = L.elem; // p的初值为第一个元素的存储位置
    while (i <= L.length && !compare(*p++,e)) {
        ++i;
    }

    if (i<=L.length)
        return i;
    else
        return ERROR;

}

// 初始条件:线性表L已存在
// 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义
Status PriorElem(SqList L, ElemType cur_e, ElemType *pre_e){
    int i = 2;
    ElemType *p = L.elem + 1;
    while (i <= L.length && *p!=cur_e) {
        p++;
        i++;
    }
    if (i>L.length)
        return INFEASIBLE;
    else{
        *pre_e = *--p;
        return OK;
    }
}

// 初始条件:线性表L已存在
// 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后续,否则操作失败,next_e无定义
Status NextElem(SqList L, ElemType cur_e, ElemType *next_e){
    int i = 1;
    ElemType *p = L.elem;
    while (i < L.length && *p!=cur_e) {
        i ++;
        p ++;
    }

    if (i == L.length)
        return INFEASIBLE;
    else{
        *next_e = *++p;
        return OK;
    }
}

// 初始条件:线性表L已存在,1<=i<=ListLength(L)+1
// 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
Status ListInsert(SqList *L, int i, ElemType e){
    ElemType *newbase,*q,*p;
    if(i<1 || i>L->length+1)
        return ERROR; // i值不合法
    if(L->length>=L->listsize) // 当前存储空间已满,增加分配
    {
        newbase = (ElemType *)realloc(L->elem,(L->listsize + LISTINCREMENT) * sizeof(ElemType));
        if(!newbase) exit(OVERLOW); // 存储分配失败
        L->elem = newbase; // 新基址
        L->listsize += LISTINCREMENT; // 增加存储容量
    }

    q=L->elem+i-1; /* q为插入位置 */
    for(p=L->elem+L->length-1;p>=q;--p) /* 插入位置及之后的元素右移 */
        *(p+1)=*p;
    *q=e; /* 插入e */
    ++L->length; /* 表长增1 */
    return OK;
}


// 初始条件:线性表L已存在且非空,1,=i<=ListLength(L)
// 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度-1
Status ListDelete(SqList *L, int i, ElemType *e){
    ElemType *p, *q;

    if (i<1 || i>L->length)
        return ERROR; // i值不合法
    p = L->elem+i-1; // p为被删除元素的位置
    *e = *p; // 被删除元素的值赋给e
    q = L->elem + L->length - 1; // 表尾元素的位置

    for (++p; p<=q; ++p) { // 被删除元素之后的元素左移
        *(p-1) = *p;
        L->length--; // 表长-1
    }
    return OK;
}

// 初始条件:线性表L已存在
// 操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败
Status ListTraverse(SqList L, void(*vi)(ElemType*)){
    ElemType *p;
    int i;
    p = L.elem;
    for (i=1; i<=L.length; i++) {
        vi(p++);
    }

    printf("\n");
    return OK;
}

测试代码:

//
//  main.c
//  arrlist
//
//  Created by liuxinming on 16/9/17.
//  Copyright © 2016年 liuxinming. All rights reserved.
//

#include <stdio.h>
#include "Arrlist.h"

// 判断是否相等的函数,Union()用到
Status equal(ElemType c1,ElemType c2)
{
    if(c1==c2)
        return TRUE;
    else
        return FALSE;
}

// 将所有在线性表Lb中但不在La中的数据元素插入到La中
void Union(SqList *La,SqList Lb)
{
    ElemType e;
    int La_len,Lb_len;
    int i;
    La_len=ListLength(*La); // 求线性表的长度
    Lb_len=ListLength(Lb);
    for(i=1;i<=Lb_len;i++)
    {
        GetElem(Lb,i,&e); // 取Lb中第i个数据元素赋给e
        if(!LocateElem(*La,e,equal)) // La中不存在和e相同的元素,则插入之
        {
           ListInsert(La,++La_len,e);
        }

    }
}

void print(ElemType *c)
{
    printf("%d ",*c);
}

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Testing start!\n");
    SqList La,Lb;
    ElemType t1,t2,t3;
    t1 = 10;
    t2 = 20;
    t3 = 30;
    int t1_length,t2_length,t3_length, i;

    // 构造一个空的线性表La
    InitList(&La);
    // 插入数据元素t1
    ListInsert(&La, 1, t1);
    // 获取线性表长度
    t1_length = ListLength(La);
    // 插入数据元素t2
    ListInsert(&La, 2, t2);
    t2_length = ListLength(La);
    // 插入数据元素t3
    ListInsert(&La, 3, t3);
    t3_length = ListLength(La);
    // 输出每次插入新元素后 表L的长度变化
    printf("t1_length=%d,t2_length=%d,t3_length=%d\n",t1_length,t2_length,t3_length);

    // 输出表La的内容
    printf("La= ");
    ListTraverse(La,print);

    // 在表Lb中插入5个元素
    InitList(&Lb);
    for (i=1; i<=5; i++) {
        ListInsert(&Lb, i, 2 * i);
    }

    // 输出表Lb的内容
    printf("Lb= ");
    ListTraverse(Lb, print);
    // 输出表Lb长度
    printf("Lb length = %d\n",ListLength(Lb));

    // La U Lb
    Union(&La, Lb);

    //输出新表L的内容
    printf("new La= ");
    ListTraverse(La,print);
    printf("end\n");
    return 0;
}

运行结果:

Testing start!
t1_length=1,t2_length=2,t3_length=3
La= 10 20 30
Lb= 2 4 6 8 10
Lb length = 5
new La= 10 20 30 2 4 6 8
end
Program ended with exit code: 0

猜你喜欢

转载自blog.csdn.net/grassroots2011/article/details/52644131