数据结构_2

学习过程主要依照中国MOOC课程,感谢MOOC,感谢浙大授课大佬。

线性表及其实现

线性表

以一元多项式表示及运算为例:

  1. 顺序存储结构直接表示。数组各分量对应多项式各项,如a[i]表示项x^i的系数ai,表示方法简单,操作也很方便,但有时会造成空间的浪费,例如表示f(x)=x+x^2000,就要开辟一个2001大小的数组来表示;
  2. 顺序存储结构表示非零项。每个非零项ai*x^i涉及两个信息:系数ai和指数i,可以将一个多项式看作一个二元数组(ai,i)的集合,每一项按照指数大小顺序存储的话,进行加减操作也比较简单;
  3. 链表结构存储非零项。链表中每个结点存储一个非零项,包括系数和指数两个数据域以及一个指针域。

线性表:由同类型数据元素构成有序序列的线性结构。

线性表的实现

  1. 线性表的顺序存储实现。利用数组的连续存储空间顺序存放线性表的各元素;
  2. 线性表的链式存储实现。不要求逻辑上相邻的两个元素物理上也相邻。

两种方式都包括移动、查找、插入、删除等操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last;
};

/* 初始化 */
List MakeEmpty()
{
List L;

L = (List)malloc(sizeof(struct LNode));
L->Last = -1;

return L;
}

/* 查找 */
#define ERROR -1

Position Find( List L, ElementType X )
{
Position i = 0;

while( i <= L->Last && L->Data[i]!= X )
i++;
if ( i > L->Last ) return ERROR; /* 如果没找到,返回错误信息 */
else return i; /* 找到后返回的是存储位置 */
}

/* 插入 */
/*注意:在插入位置参数P上与课程视频有所不同,课程视频中i是序列位序(从1开始),这里P是存储下标位置(从0开始),两者差1*/
bool Insert( List L, ElementType X, Position P )
{ /* 在L的指定位置P前插入一个新元素X */
Position i;

if ( L->Last == MAXSIZE-1) {
/* 表空间已满,不能插入 */
printf("表满");
return false;
}
if ( P<0 || P>L->Last+1 ) { /* 检查插入位置的合法性 */
printf("位置不合法");
return false;
}
for( i=L->Last; i>=P; i-- )
L->Data[i+1] = L->Data[i]; /* 将位置P及以后的元素顺序向后移动 */
L->Data[P] = X; /* 新元素插入 */
L->Last++; /* Last仍指向最后元素 */
return true;
}

/* 删除 */
/*注意:在删除位置参数P上与课程视频有所不同,课程视频中i是序列位序(从1开始),这里P是存储下标位置(从0开始),两者差1*/
bool Delete( List L, Position P )
{ /* 从L中删除指定位置P的元素 */
Position i;

if( P<0 || P>L->Last ) { /* 检查空表及删除位置的合法性 */
printf("位置%d不存在元素", P );
return false;
}
for( i=P+1; i<=L->Last; i++ )
L->Data[i-1] = L->Data[i]; /* 将位置P+1及以后的元素顺序向前移动 */
L->Last--; /* Last仍指向最后元素 */
return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;

/* 查找 */
#define ERROR NULL

Position Find( List L, ElementType X )
{
Position p = L; /* p指向L的第1个结点 */

while ( p && p->Data!=X )
p = p->Next;

/* 下列语句可以用 return p; 替换 */
if ( p )
return p;
else
return ERROR;
}

/* 带头结点的插入 */
/*注意:在插入位置参数P上与课程视频有所不同,课程视频中i是序列位序(从1开始),这里P是链表结点指针,在P之前插入新结点 */
bool Insert( List L, ElementType X, Position P )
{ /* 这里默认L有头结点 */
Position tmp, pre;

/* 查找P的前一个结点 */
for ( pre=L; pre&&pre->Next!=P; pre=pre->Next ) ;
if ( pre==NULL ) { /* P所指的结点不在L中 */
printf("插入位置参数错误\n");
return false;
}
else { /* 找到了P的前一个结点pre */
/* 在P前插入新结点 */
tmp = (Position)malloc(sizeof(struct LNode)); /* 申请、填装结点 */
tmp->Data = X;
tmp->Next = P;
pre->Next = tmp;
return true;
}
}

/* 带头结点的删除 */
/*注意:在删除位置参数P上与课程视频有所不同,课程视频中i是序列位序(从1开始),这里P是拟删除结点指针 */
bool Delete( List L, Position P )
{ /* 这里默认L有头结点 */
Position tmp, pre;

/* 查找P的前一个结点 */
for ( pre=L; pre&&pre->Next!=P; pre=pre->Next ) ;
if ( pre==NULL || P==NULL) { /* P所指的结点不在L中 */
printf("删除位置参数错误\n");
return false;
}
else { /* 找到了P的前一个结点pre */
/* 将P位置的结点删除 */
pre->Next = P->Next;
free(P);
return true;
}
}

广义表

广义表是线性表的推广,对于线性表而言,n个元素都是基本的单元素,而在广义表中,这些元素不仅可以是单元素也可以是另一个广义表。

多重链表

链表中的节点可能同时隶属于多个链,也就是说多重链表中结点的指针域会有多个,但包含两个指针域的链表并不一定是多重链表,例如双向链表不是多重链表。树、图等复杂的数据结构都可以采用多重链表来存储,
典型的多重链表:十字链表(用来存储稀疏矩阵等)

堆栈及其实现#

堆栈

堆栈:具有一定操作约束的线性表。
只在一端(栈顶,Top)做插入(入栈,Push)、删除(出栈,Pop),后入先出(Last In First Out,LIFO)

堆栈的实现

  1. 顺序存储实现。用一个一维数组以及一个一个记录栈顶元素位置的变量组成。
  2. 链式存储实现。栈的链式存储结构实际上就是一个单项链,叫做链栈。插入和删除操作只能在链栈的栈顶进行,栈顶指针Top应该在链表的头。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    typedef int Position;
    struct SNode {
    ElementType *Data; /* 存储元素的数组 */
    Position Top; /* 栈顶指针 */
    int MaxSize; /* 堆栈最大容量 */
    };
    typedef struct SNode *Stack;

    Stack CreateStack( int MaxSize )
    {
    Stack S = (Stack)malloc(sizeof(struct SNode));
    S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    S->Top = -1;
    S->MaxSize = MaxSize;
    return S;
    }

    bool IsFull( Stack S )
    {
    return (S->Top == S->MaxSize-1);
    }

    bool Push( Stack S, ElementType X )
    {
    if ( IsFull(S) ) {
    printf("堆栈满");
    return false;
    }
    else {
    S->Data[++(S->Top)] = X;
    return true;
    }
    }

    bool IsEmpty( Stack S )
    {
    return (S->Top == -1);
    }

    ElementType Pop( Stack S )
    {
    if ( IsEmpty(S) ) {
    printf("堆栈空");
    return ERROR; /* ERROR是ElementType的特殊值,标志错误 */
    }
    else
    return ( S->Data[(S->Top)--] );
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    typedef struct SNode *PtrToSNode;
    struct SNode {
    ElementType Data;
    PtrToSNode Next;
    };
    typedef PtrToSNode Stack;

    Stack CreateStack( )
    { /* 构建一个堆栈的头结点,返回该结点指针 */
    Stack S;

    S = (Stack)malloc(sizeof(struct SNode));
    S->Next = NULL;
    return S;
    }

    bool IsEmpty ( Stack S )
    { /* 判断堆栈S是否为空,若是返回true;否则返回false */
    return ( S->Next == NULL );
    }

    bool Push( Stack S, ElementType X )
    { /* 将元素X压入堆栈S */
    PtrToSNode TmpCell;

    TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
    TmpCell->Data = X;
    TmpCell->Next = S->Next;
    S->Next = TmpCell;
    return true;
    }

    ElementType Pop( Stack S )
    { /* 删除并返回堆栈S的栈顶元素 */
    PtrToSNode FirstCell;
    ElementType TopElem;

    if( IsEmpty(S) ) {
    printf("堆栈空");
    return ERROR;
    }
    else {
    FirstCell = S->Next;
    TopElem = FirstCell->Data;
    S->Next = FirstCell->Next;
    free(FirstCell);
    return TopElem;
    }
    }

    队列及其实现

    队列

    队列:具有一定操作约束的线性表。
    只在一端插入(入队,AddQ),在另一端删除(出队,DeleteQ),先进先出(FIFO)。

    队列的实现

  3. 顺序存储实现。由一个一维数组和一个记录队列头元素位置的变量front以及一个记录队列尾元素位置的变量rear组成。
  4. 链式存储实现。队列的链式存储结构实际上也是一个单项链。插入和删除操作在链表的两头进行,队列指针front和rear分别指向链表的头和尾。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    typedef int Position;
    struct QNode {
    ElementType *Data; /* 存储元素的数组 */
    Position Front, Rear; /* 队列的头、尾指针 */
    int MaxSize; /* 队列最大容量 */
    };
    typedef struct QNode *Queue;

    Queue CreateQueue( int MaxSize )
    {
    Queue Q = (Queue)malloc(sizeof(struct QNode));
    Q->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    Q->Front = Q->Rear = 0;
    Q->MaxSize = MaxSize;
    return Q;
    }

    bool IsFull( Queue Q )
    {
    return ((Q->Rear+1)%Q->MaxSize == Q->Front);
    }

    bool AddQ( Queue Q, ElementType X )
    {
    if ( IsFull(Q) ) {
    printf("队列满");
    return false;
    }
    else {
    Q->Rear = (Q->Rear+1)%Q->MaxSize;
    Q->Data[Q->Rear] = X;
    return true;
    }
    }

    bool IsEmpty( Queue Q )
    {
    return (Q->Front == Q->Rear);
    }

    ElementType DeleteQ( Queue Q )
    {
    if ( IsEmpty(Q) ) {
    printf("队列空");
    return ERROR;
    }
    else {
    Q->Front =(Q->Front+1)%Q->MaxSize;
    return Q->Data[Q->Front];
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    typedef struct Node *PtrToNode;
    struct Node { /* 队列中的结点 */
    ElementType Data;
    PtrToNode Next;
    };
    typedef PtrToNode Position;

    struct QNode {
    Position Front, Rear; /* 队列的头、尾指针 */
    int MaxSize; /* 队列最大容量 */
    };
    typedef struct QNode *Queue;

    bool IsEmpty( Queue Q )
    {
    return ( Q->Front == NULL);
    }

    ElementType DeleteQ( Queue Q )
    {
    Position FrontCell;
    ElementType FrontElem;

    if ( IsEmpty(Q) ) {
    printf("队列空");
    return ERROR;
    }
    else {
    FrontCell = Q->Front;
    if ( Q->Front == Q->Rear ) /* 若队列只有一个元素 */
    Q->Front = Q->Rear = NULL; /* 删除后队列置为空 */
    else
    Q->Front = Q->Front->Next;
    FrontElem = FrontCell->Data;

    free( FrontCell ); /* 释放被删除结点空间 */
    return FrontElem;
    }
    }

以上。

:转载文章请注明出处,谢谢~