1.1线性表(List)及实现
1.1.1线性表的定义
- 由同类型数据元素构成有序序列的线性结构
- 表中元素个数成为L的表长
- 表中无元素时,称为空表
- 表的起始位置称为表头,结束位置称为表尾
1.1.2线性表的存储实现
数组和链表的空间分配情况:
- 数组在静态存储分配情形下,存储元素数量受限制,动态存储分配情形下,虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且如果内存中没有更大块连续存储空间将导致分配失败;即数组从栈中分配空间,,对于程序员方便快速,但自由度小。
- 链表存储的节点空间只在需要的时候申请分配,只要内存中有空间就可以分配,操作比较灵活高效;即链表从堆中分配空间, 自由度大但申请管理比较麻烦。
线性表的基本操作:
(1)List MakeEmpty():初始化一个空线性表L
(2)ElementType FindKth(int k,List L):根据位置k,查找返回位置的元素
(3)int Find(ElementType X,List L):在线性表L中查找X第一次出现的位置
(4)void Insert(ElementType X,int i,List L):在i位置前插入元素X
(5)void Delete(int i,List L):删除i位置的元素
(6)int Length(List L):返回线性表L的长度
1.1.2.1线性表的顺序存储实现
1 #define MAXSIZE 100//定义Data的最大值 2 typedef int ElementType; 3 typedef struct LNode *List; 4 struct LNode 5 { 6 ElementType Data[MAXSIZE]; 7 int Last;//定义线性表的最后一个元素的下标或者记录表长的变量也可 8 }; 9 List L; 10 11 //初始化 12 List MakeEmpty() { 13 List L; 14 L = (List)malloc(sizeof(LNode));//申请一个线性表的空间 15 L->Last = -1; 16 return L; 17 } 18 19 //按值查找 20 int Find(ElementType X, List L) { 21 int i = 0; 22 while (i <= L->Last&&L->Data[i] != X) { 23 i++; 24 } 25 if (L->Last < i) { 26 return -1;//没找到,是i>last的时候跳出的 27 } 28 else 29 return i;//找到了,是相等的时候跳出的 30 } 31 32 //插入 33 void Insert(ElementType X, int i, List L) { 34 int j; 35 if (L->Last == MAXSIZE - 1) { 36 printf("表满"); 37 return; 38 } 39 if (i < 0 || L->Last + 1<i) { 40 printf("位置不合法"); 41 return; 42 } 43 for (j = L->Last; j >= i; j--) { 44 L->Data[j + 1] = L->Data[j];//从后往前 45 } 46 L->Data[i] = X; 47 L->Last++;//last仍然指向最后一个元素 48 return; 49 } 50 51 //删除 52 void Delete(int i, List L) { 53 int j; 54 if (i<0 || i>L->Last) { 55 printf("L->Data[%d]不存在元素",i); 56 return; 57 } 58 for (j = i; j <= L->Last; j++) { 59 L->Data[j] = L->Data[j+1]; 60 } 61 L->Last--; 62 return; 63 } 64 65 //按序查找 顺序存储最大的优点 66 ElementType FindKth(int k, List L) { 67 if (k<0 || k>L->Last) { 68 printf("L->Data[%d]不存在元素", k); 69 return 0; 70 } 71 return L->Data[k]; 72 } 73 74 //表长 75 int Length(List L) { 76 return L->Last + 1; 77 }
1.1.2.2线性表的链表存储实现
1 typedef int ElementType; 2 typedef struct LNode *List; 3 struct LNode 4 { 5 ElementType Data;//数据域 6 List Next;//下一个链表的地址 7 }; 8 List L;//L既是单链表的名字又是头指针的名字 9 10 //初始化 11 //建立一个带有头结点的链表 12 List MakeEmpty1() { 13 List L = (List)malloc(sizeof(LNode));//申请头结点 14 if (L == NULL) { 15 printf("申请空间失败!"); 16 } 17 else { 18 L->Data = 100; 19 L->Next = NULL;//头结点指向NULL 20 } 21 return L; 22 } 23 24 //建立不带头结点的链表 25 List MakeEmpty2() { 26 List L = NULL;//头指针不指向任何结点 27 return L; 28 } 29 30 //表长 31 int Length(List L) { 32 List p = L;//定义一个List类型的指针,将其初始化为头指针 33 int len = 0; 34 while (p) { 35 p = p->Next; 36 len++; 37 } 38 return len; 39 } 40 41 //按序查找 42 List FindKth(int k,List L) { 43 List p = L; 44 int i = 1;//链表从1开始 45 while (p&&i<k) 46 { 47 p = p->Next; 48 i++; 49 } 50 if (i == k) 51 return p;//返回结点 52 else 53 return NULL; 54 } 55 56 //按值查找 57 List Find(ElementType X, List L) { 58 List p = L; 59 while (p&&p->Data != X) { 60 p = p->Next; 61 } 62 //找到了返回p 63 //未找到,此时p是NULL 64 return p; 65 } 66 67 //插入新节点 68 List Insert(ElementType X, int i, List L) { 69 List s = (List)malloc(sizeof(LNode));//申请一个新节点 70 s->Data = X; 71 //新节点插入在表头 72 if (i == 1) { 73 s->Next = L; 74 return s;//因为此时s就是第一个节点 75 } 76 //插入的节点在中间 p表示第i-1位的节点 77 List p = FindKth(i - 1, L); 78 if (!p) {//如果第i个节点不存在 79 printf("节点错误"); 80 return NULL; 81 } 82 else { 83 s->Data = X; 84 s->Next = p->Next; 85 p->Next = s; 86 return L; 87 } 88 } 89 90 //删除 91 List Delete(int i, List L) { 92 List s, p; 93 //如果删除头结点 94 if (i == 1) { 95 s = L; 96 if (L) {//如果不为空 97 L = L->Next;//现在头结点变成原来的第二个节点 98 } 99 else 100 return NULL; 101 free(s); 102 return L; 103 } 104 p = FindKth(i - 1, L); 105 if (!p || !(p->Next)) {//如果i-1或者i不存在 106 printf("节点错误"); 107 return NULL; 108 } 109 s = p->Next; 110 p->Next = s->Next; 111 free(s); 112 return L; 113 } 114 115 //输出链表元素 116 void Print(List L) { 117 List t; 118 int flag = 1; 119 printf("当前列表为:"); 120 for (t = L; t; t = t->Next) { 121 printf("%d ", t->Data); 122 flag = 0; 123 } 124 if (flag) 125 printf("NULL"); 126 printf(" "); 127 }