Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

数据结构:线性表之链式存储结构

$
0
0

为了表示每个数据元素ai与其直接后继元素ai+1之间的逻辑关系,对数据ai,除了存储其自身的信息之外,还需存储一个指示其

直接后继的信息(即直接后继的存储位置)。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。N个结点链结成一个链表,

即为线性表(a1,a2,...,an)的链式存储结构,因为此链表的每个节点中只包含一个指针域,所以叫做单链表。

我们把链表中的第一个结点的存储位置叫做头指针,,为了更方便地对链表进行操作,如删除第一个结点的特殊情况

(第一个结点没有前驱,而要摘除一个结点需要首先找到它的前驱才能做摘除操作),经常在单链表的第一个结点前附设一个结点,

称为头节点,这样头指针就指向了头节点。


示例程序:(改编自《大话数据结构》)

 C++ Code 
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;

typedef int ElemType;

typedef struct  Node
{
    ElemType data;
    struct Node *next;
} Node;

typedef Node *NodePtr;

bool InitList(NodePtr *Npp)
{
    *Npp = (NodePtr)malloc(sizeof(Node));
    if (!(*Npp))
        return false//分配失败
    (*Npp)->next = NULL;
    return true;
}

bool ListEmpty(NodePtr Np)
{
    if (Np->next == NULL)
        return true;
    else
        return false;
}

bool ClearList(NodePtr *Npp)
{
    cout << "Clear List..." << endl;
    NodePtr p = *Npp;
    if (!(p->next))
        return true;
    while (p->next)
    {
        NodePtr q = p->next;
        p->next = q->next;
        free(q);
    }
    return true;
}

int ListLength(NodePtr Np)
{
    cout << "List's length : ";
    NodePtr p = Np->next;
    int i = 0;
    while (p)
    {
        p = p->next;
        ++i;
    }
    return i;
}

bool GetElem(NodePtr Np, int pos, ElemType *ptr)
{
    cout << "Get Item from pos " << pos << " : ";
    NodePtr p = Np->next;
    int i = 1;
    while (p && i < pos)
    {
        p = p->next;
        ++i;
    }
    if (!p)
        return false;
    *ptr = p->data;
    return true;
}

int LocateElem(NodePtr Np, ElemType Elem)
{
    cout << "Item " << Elem << "'s pos : ";
    NodePtr p = Np->next;
    int i = 1;
    while (p && p->data != Elem)
    {
        p = p->next;
        ++i;
    }
    if (!p)
        return 0;
    return i;
}

bool ListInsert(NodePtr *Npp, int pos, ElemType Elem)
{
    cout << "Insert List pos " << pos << " Item " << Elem << endl;
    NodePtr p = *Npp;
    int i = 1;
    while (p && i < pos)
    {
        p = p->next;
        ++i;
    }
    if (!p)
        return false;
    NodePtr In = (NodePtr)malloc(sizeof(Node));
    In->data = Elem;
    In->next = p->next;
    p->next = In;
    return true;
}

bool ListDelete(NodePtr *Npp, int pos, ElemType *ptr)
{
    cout << "Delete List Item in pos " << pos << endl;
    NodePtr p = *Npp;
    int i = 1;
    while (p && i < pos)
    {
        p = p->next;
        ++i;
    }
    if (!p)
        return false;
    NodePtr q = p->next;
    *ptr = q->data;
    p->next = q->next;
    free(q);
    return true;
}

bool ListTraverse(NodePtr Np)
{
    cout << "List's Items : ";
    NodePtr p = Np->next;
    while (p)
    {
        cout << p->data << ' ';
        p = p->next;
    }
    cout << endl;
    return true;
}

void CreateListHead(NodePtr *Npp, int num)
{
    cout << "Create List from Head ..." << endl;
    if (*Npp != NULL)
        free(*Npp);
    *Npp = (NodePtr)malloc(sizeof(Node));
    (*Npp)->next = NULL;
    srand(time(NULL));
    for (int i = 0; i < num; i++)
    {
        NodePtr p = (NodePtr)malloc(sizeof(Node));
        p->data = rand() % 100 + 1//随机数
        p->next = (*Npp)->next;
        (*Npp)->next = p;
    }
}

void CreateListTail(NodePtr *Npp, int num)
{
    cout << "Create List from Tail ..." << endl;
    if (*Npp != NULL)
        free(*Npp);
    *Npp = (NodePtr)malloc(sizeof(Node));
    (*Npp)->next = NULL;
    srand(time(NULL));
    NodePtr tail = *Npp;
    for (int i = 0; i < num; i++)
    {
        NodePtr p = (NodePtr)malloc(sizeof(Node));
        p->data = rand() % 100 + 1;
        tail->next = p;
        tail = p;
    }
    tail->next = NULL;
}

int main(void)
{
    NodePtr Np;
    InitList(&Np);
    for (int i = 1; i < 5; i++)
        ListInsert(&Np, i, i);
    if (!ListEmpty(Np))
        cout << ListLength(Np) << endl;
    ListTraverse(Np);
    cout << LocateElem(Np, 3) << endl;
    int get;
    GetElem(Np, 2, &get);
    cout << get << endl;
    ClearList(&Np);
    cout << ListLength(Np) << endl;
    CreateListHead(&Np, 10);
    ListTraverse(Np);
    int result;
    ListDelete(&Np, 5, &result);
    ListTraverse(Np);
    ClearList(&Np);
    CreateListTail(&Np, 10);
    ListTraverse(Np);
    ClearList(&Np);
    return 0;
}
输出为:


如果限定每次只在链表的头部插入和删除元素,就形成一个LIFO的访问序列,所以在链表头部插入和删除元素的操作实现了

堆栈的push和pop操作。当然基于单链表也是可以实现队列的enqueue和dequeue操作的,比如在每次在头部插入而在尾部删除,

或者反过来都是一样的道理。

作者:Simba888888 发表于2013-4-21 10:12:45 原文链接
阅读:64 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>