数据结构之线性表

简介:

一、线性表定义:

   线性表是一个线性结构,它是一个含有n≥0个结点的有限序列,其中的结点,有且仅有一个开始结点(第一元素)没有前驱但有一个后继结点,有且仅有一个终端结点(最后节点)没有后继但有一个前驱结点,其它的结点都有且仅有一个前驱和一个后继结点。一般地,一个线性表可以表示成一个线性序列:k1,k2,…,kn,其中k1是开始结点,kn是终端结点。

   上述定义可以用下列图像记忆

    如一对有序序列(A,B,C,............Z)

图表示为

^A(第一节点,没有前驱但有一个后继结点),B,C ……(其它的结点都有且仅有一个前驱和一个后继结点)……….Z(最后节点,没有后继但有一个前驱结点),^

   总结:凡是符合上图特点的均可以认为是线性表。


二、线性表的顺序表示链式表示区别

顺序表


存储图如下

特点:

   一、逻辑上相邻的数据元素,物理存储位置也相邻。(逻物一致)

   二、顺序表的存储空间需要预先分配。    

 优点:

  (1)方法简单,各种高级语言中都有数组,容易实现。(语言通用性)

  (2)不用为表示节点间的逻辑关系而增加额外的存储开销。(内存节约性)

  (3)顺序表具有按元素序号随机访问的特点。(逻物一致性)

缺点:

  (1)在顺序表中做插入、删除操作时,平均移动表中的一半元素,因此对n较大的顺序表效率低。(操作低效率)

  (2)需要预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。(内存固定性)


链式表

存储图如下





特点:

一、逻辑上相邻的数据元素,物理存储位置不一定相邻。(逻物不一定一致)

二、它使用指针实现元素之间的逻辑关系。并且,链表的存储空间是动态分配的。

链表的最大特点是:插入、删除运算方便。(插入、删除方便)

   优点:

(1)插入、删除运算方便。(插入、删除方便)

    (2)内存空间动态分配使得内存使用率高内存不易溢出(内存动态分配性)

   缺点:

 (1)要占用额外的存储空间存储元素之间的关系,存储密度降低。存储密度是指一个节点中数据元素所占的存储单元和整个节点所占的存储单元之比。(内存浪费内存有效使用率低)

  (2)链表不是一种随机存储结构,不能随机存取元素。(逻物不一致)

   总结: 顺序表是一种牺牲cpu为代价但节省内存的数据存储方式,链式表是牺牲内存代价的高效率的存储方式。
实践应用中怎样选取存储结构呢?

   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
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
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
#define OVERFLOW -2
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
typedef  int  Status;
typedef  int  ElemType;
typedef  struct
{
     int  *elem;
     int  length;
     int  listsize;
}SqList;
Status InitList_Sq(SqList &L)
{
     L.elem = (ElemType *) malloc (LIST_INIT_SIZE *  sizeof (ElemType));
     if  (!L.elem)  exit (OVERFLOW);
     L.length = 0;
     L.listsize = LIST_INIT_SIZE;
     return  OK;
}
//插入
Status ListInsert_Sq(SqList &L,  int  i, ElemType e)
{
     ElemType *newbase, *q, *p;
     if (i < 1 || i > L.length + 1)  return  ERROR;
     if (L.length >= L.listsize)
     {
         newbase = (ElemType *) realloc (L.elem, (L.listsize + LISTINCREMENT) *  sizeof (ElemType));
         if (!newbase)  exit (OVERFLOW);
         L.elem = newbase;
         L.listsize += LISTINCREMENT;
     }
     q = &(L.elem[i - 1]);
     for (p = &(L.elem[L.length - 1]); p >= q; --p)
         *(p+1) = *p;
     *q = e;
     ++L.length;
     return  OK;
}
//创建
Status CreateList_Sq(SqList &L,  int  n){
     int  i; ElemType e;
     printf ( "Please input %d elements:\n" , n);
     for (i = 1; i <= n; i++){
         scanf ( "%d" ,&e);
         ListInsert_Sq(L, i, e);
     }
     return  OK;
}
//删除
Status DeleteList_Sq(SqList &L, int  i, ElemType *e){
     ElemType *p, *q;
     if (i <= 0 || i > L.length)  return  ERROR;
     p = &L.elem[i-1];
     *e = *p;
     q = L.elem + L.length ;
     for (++p; p < q; ++p)
         *(p - 1) = *p;
     --L.length;
     return  OK;
}
//查找
Status LocateElem(SqList L,  int  num){
     int  i = 1;
     ElemType *p; 
     p = L.elem;
     while  (i <= L.length && *p != num )
     {   ++i;    ++p;    }
     if (i < L.length)
         return  i;
     else
         return  0;
}
//排序
Status ListAscend_Sq(SqList &L){
     int  i, j, k;
     ElemType t;
     for (i = 0; i < L.length; i++)
     {
         k = i;
         for (j = i+1; j < L.length; j++)
             if (L.elem[j] < L.elem[k])
                 k = j;
         if (k != i)
         {
             t = L.elem[i];
             L.elem[i] = L.elem[k];
             L.elem[k] = t;
         }
     }
     return  OK;
}
//输出
void  Print_Sq(SqList L)
{
     int  i;
     for (i = 0; i < L.length; i++)
     printf ( "%d " ,L.elem[i]);
     printf ( "\n" );
}
void  main()
{
     Status i, e, num, de, location, position, result;
     SqList MyList;
     InitList_Sq(MyList); //初始化
                                                                  
     CreateList_Sq(MyList, 10); //创建
     printf ( "\n" );
     //插入
     printf ( "Please input the number's position and the number to be inserted:" );
     scanf ( "%d,%d" , &i, &e);
     ListInsert_Sq(MyList,i, e);
     printf ( "\n" );
     printf ( "Inserted list:\n" );
     Print_Sq(MyList);
     printf ( "\n" );
                                                                  
     //删除
     printf ( "Please input the position(to be deleted):" );
     scanf ( "%d" , &position);
     result = DeleteList_Sq(MyList, position, &de);
     if (result == OK)
         printf ( "The %dth element %d has been deleted.\n" , position, de);
     Print_Sq(MyList);
     //查找
     printf ( "\n" );
     printf ( "Please input the located number:" );
     scanf ( "%d" ,&num);
     location = LocateElem(MyList, num);
     if (location < 1)
         printf ( "DO NOT EXIST!" );
     else
         printf ( "Location:%d" ,location);
                                                                  
     printf ( "\n\n" );
     ListAscend_Sq(MyList); //排序
//  printf("\n\n");
     printf ( "The sorted list by ascending:\n" );
     Print_Sq(MyList); //输出
     printf ( "\n" );
     free (MyList.elem); //释放空间
}





   以链式存储为例的代码如下:

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
#include<stdio.h>
#include<stdlib.h>
#define TRUE    1
#define FALSE   0
#define OK  1
#define ERROR   0
#define INFEASIBLE  -1
typedef  int  Status;
typedef  int  ElemType;
typedef  struct  LNode { //定义类型链式节点
     ElemType  data;
     struct  LNode * next;
}LNode, *LinkList;
Status InitList_L(LinkList &L){ //初始化链表L,链表的节点个数初始化data = 0; next = null
     L = (LinkList) malloc ( sizeof (LNode)); //分配内存空间
     if (!L)  return  ERROR;
     L->data = 0; //节点个数,或称为表长(表的长度)
     L->next = NULL;
     return  OK;
}
Status Insert_L(LinkList &L,  int  i, ElemType e){ //向链表插入元素e
     LNode *p, *q;
     int  j = 0;
     p = L;
     while (p && j < i - 1){
         p = p->next; ++j; 
     }
     if (!p || j > i - 1)  return  ERROR;
     q = (LinkList) malloc ( sizeof (LNode));
     q->data = e; //insert element
     q->next = p->next;
     p->next = q;
     L->data++; //每插入也节点,表长自加1
     return  OK;
}
Status Delete_L(LinkList &L, int  i, ElemType e){ //删除节点e
     LNode *p, *q;
     p = L;
     int  j = 0;
     while (p->next && j < i - 1){
         p = p->next;
         ++j;
     }
     if (!(p->next) || j > i - 1)  return  ERROR;
     q = p->next;
     p->next = q->next;
     e = q->data;
     free (q);
     L->data--; //每删除一个节点,表长自减1
     return  OK;
}
Status GetElem_L(LinkList L,  int  i, ElemType &e){ //获取第i个元素,赋值于e
     LNode *p;
     int  j = 1;
     p = L->next;
     while (p && j < i){
         p = p->next;
         ++j;
     }
     if (!p || j > i)   return  ERROR;
     e = p->data;
     return  OK;
}
     Status Create_L(LinkList &L){ //创建链表,赋值元素
     ElemType temp;
     printf ( "Please input data<9999>ending\n" );
     scanf ( "%d" , &temp);
     while (temp != 9999){
         Insert_L(L, L->data+1, temp);
         scanf ( "%d" , &temp);
     }
     return  OK;
}
Status Traverse_L(LinkList L){ //遍历线性表
     LNode *p = L->next;
     printf ( "List contains %d elements:\n" ,L->data);
     while (p){
         printf ( "%5d-->" ,p->data);
         p = p->next;
     }
     printf ( "NULL\n" );
     return  OK;
}
Status DeleteBet(LinkList &L, ElemType mink, ElemType maxk){ //删除值在(mink,maxk)之间的值
     LinkList p, q;
     p = L;
     if ((mink >= maxk) ||(p->next == NULL))  exit (ERROR);
     while (p){
                                                                                                     
         if (p->next->data > mink){
             while (p->next->data < maxk){
                 q = p->next;
                 p->next = p->next->next;
                 free (q);
                 L->data --;
             }
             break ;
         }
         p = p->next;
     }
     return  OK;
}
void   main(){
     LinkList L;  int  i, i1, i2, e, e1, e2, j1, j2;
     InitList_L(L); //初始化链表
     Create_L(L); //赋值链表
     printf ( "The length is:%d\n" , L->data);
     Traverse_L(L); //遍历输出节点值
     printf ( "GetElem i:" );    scanf ( "%d" , &i);
     GetElem_L(L, i, e);
     printf ( "The NO.%d element is:%d \n" , i, e);
                                                                                                     
     printf ( "InsertPosition:" );   scanf ( "%d" , &i1);
     printf ( "Insert element:" );
     scanf ( "%d" , &e1);
     Insert_L(L, i1, e1);
     Traverse_L(L); //遍历输出节点值
     printf ( "Delete position:" );  scanf ( "%d" , &i2);
     Delete_L(L, i2, e2);
     Traverse_L(L); //遍历输出节点值
     printf ( "\nDelete between(a,b):" );
     scanf ( "%d,%d" ,&j1, &j2);
                                                                                                     
     DeleteBet(L, j1, j2);
     printf ( "The result is:%d\n" );
     Traverse_L(L); //遍历输出节点值
}



四、知识点回顾

线性表的链式存储及特点

–逻物不一定一致、顺序存取、空间利用充分、插删方便

• 单链表(线性链表)及C语言实现

• 头指针、头结点、首元结点

• 单链表的建立、查找、插入、删除、输出

• 单链表与顺序表的比较,及挑



本文转自lilin9105 51CTO博客,原文链接:http://blog.51cto.com/7071976/1206925,如需转载请自行联系原作者

相关文章
|
存储 C语言
数据结构中的线性表链式存储介绍及其基本操作
链式存储是线性表的一种重要存储方式,它通过节点和指针的结构,实现了灵活的动态存储管理。本文介绍了单向链表的基本操作,并提供了相应的C语言代码示例。理解和掌握链表的操作对学习和应用数据结构具有重要意义。希望这篇博客能帮助你更好地理解线性表的链式存储。
430 2
|
11月前
|
存储 算法 测试技术
【C++数据结构——线性表】求集合的并、交和差运算(头歌实践教学平台习题)【合集】
本任务要求编写程序求两个集合的并集、交集和差集。主要内容包括: 1. **单链表表示集合**:使用单链表存储集合元素,确保元素唯一且无序。 2. **求并集**:遍历两个集合,将所有不同元素加入新链表。 3. **求交集**:遍历集合A,检查元素是否在集合B中存在,若存在则加入结果链表。 4. **求差集**:遍历集合A,检查元素是否不在集合B中,若满足条件则加入结果链表。 通过C++代码实现上述操作,并提供测试用例验证结果。测试输入为两个集合的元素,输出为有序集合A、B,以及它们的并集、交集和差集。 示例测试输入: ``` a c e f a b d e h i ``` 预期输出:
309 7
|
11月前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
502 5
|
11月前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】
本文档介绍了线性表的基本运算任务,涵盖顺序表和链表的初始化、销毁、判定是否为空、求长度、输出、查找元素、插入和删除元素等内容。通过C++代码示例详细展示了每一步骤的具体实现方法,并提供了测试说明和通关代码。 主要内容包括: - **任务描述**:实现顺序表的基本运算。 - **相关知识**:介绍线性表的基本概念及操作,如初始化、销毁、判定是否为空表等。 - **具体操作**:详述顺序表和链表的初始化、求长度、输出、查找、插入和删除元素的方法,并附有代码示例。 - **测试说明**:提供测试输入和预期输出,确保代码正确性。 - **通关代码**:给出完整的C++代码实现,帮助完成任务。 文档
342 5
|
算法
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
145 0
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
165 6
|
存储
【数据结构】线性表和顺序表
【数据结构】线性表和顺序表
121 1
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
01(数据结构考研)线性表相关操作代码
01(数据结构考研)线性表相关操作代码
191 0
|
存储 C语言
数据结构之线性表的初始化及其操作
数据结构之线性表的初始化及其操作
206 0

热门文章

最新文章