基本数据结构-线性表
Macre算法系列笔记是综合 严卫敏《数据结构(c语言版)》书籍,以及考研408辅导讲义–王道408计算机考研的内容上,结合 罗永浩《算法竞赛》内容,加强编码能力和解决问题的实践能力。 感谢以上所提及的个人和机构对计算机教学领域做出的杰出贡献。(应该在有一定编程语言和调试能力下尽量去coding和调试!)。
可以作为数据结构与算法课程的实验去copy本内容代码!
先记录基本数据结构具体内容,算法应用在最后!
一、线性表基本定义
一个数据结构包含逻辑结构、存储结构以及作用在元素上的方法。
(1)逻辑结构
线性表(linear line)是最简单的数据结构。非空表记为D=(a1, a2 , …, ai-1, ai , …, an)。用数学表达式表示为:
D = { a i ∣ a i ∈ T , i = 1 , 2 , . . . , n , n ≥ 0 } D=\,\,\left\{ ai|ai∈T,i=1,2,…,n,n≥0 \right\} D={ ai∣ai∈T,i=1,2,…,n,n≥0}
其是一个有限序列,表中每个表项都是相继排列的,每两个相邻表象都有直接前驱和直接后继关系,也就是说,线性表中仅存在唯一的一个表头(haed)、唯一的一个表尾(tail)。这表明表中数据之间的关系是线性表中相邻的数据元素ai-1和ai之间存在序偶关系(ai-1, ai),即ai-1是ai的前驱, ai是ai-1的后继;a1无前驱,an无后继,其它每个元素有且仅有一个前驱和一个后继。
R = { < a i − 1 , a i > ∣ a i − 1 , a i ∈ D , i = 2 , . . . , n } R\text{=}\left\{ <a_{i-1},a_i>|a_{i-1},a_i∈D,i=2,…,n \right\} R={ <ai−1,ai>∣ai−1,ai∈D,i=2,…,n}
(2)存储结构
主要是顺序存储和链式存储。
顺序存储:逻辑上相邻的元素在物理位置上也相邻。
链式存储:逻辑与物理存储位置无关。
(3)作用在次数据结构上的操作:
一个线性表内:元素的增加、删除、查找等;
线性表之间:合并、比较等
二、顺序存储的线性表- 顺序表 SQlist
1 2 3 4 #include <stdio.h> #include <stdlib.h> typedef int Elemtype; typedef int Status;
2.1 静态数组
1 2 3 4 5 6 7 8 9 #define Maxsize 20 typedef int Status; typedef struct Sqlsit { Elemtype data[Maxsize]; int length; }Sqlist;
2.2 动态数组
1 2 3 4 5 6 7 typedef struct { Elemtype *elem; int length; int size; }Sqlist;
2.3 方法
函数具体说明看函数里第一行注释! 对于动态的!
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 Sqlist initSqlist () { Sqlist L; L.elem = (Elemtype *)malloc(Maxsize*sizeof(Elemtype)); if (!L.elem) { printf("初始化失败!" ); exit(0 ); } L.length = 0 ; L.size = Maxsize; return L; } Status creatList (Sqlist *L,int n) { if (n < 0 ) return 0 ; if (n > L->size) { Elemtype *new = (Elemtype *)realloc(L->elem,L->size*2 *sizeof(Elemtype)); L->elem = new ; L->size *=2 ; } for (int i = 0 ; i < n; i++) { scanf("%d" ,&L->elem[i]); L->length++; } return 1 ; } void displayTable (Sqlist t) { for (int i = 0 ; i < t.length; i++) { printf("%d " ,t.elem[i]); } printf("\n" ); } Status listinsert (Sqlist *L,int i,Elemtype x) { if (L->length>=L->size) { Elemtype *new = (Elemtype *)realloc(L->elem,sizeof(Elemtype)*L->size*2 ); L->size *= 2 ; } if (i < 0 || i > L->length) { printf("请输入合法的位置!" ); return 0 ; } for (int j = L->length-1 ; j >= i-1 ; j--) { L->elem[j+1 ] = L->elem[j]; } L->elem[i-1 ] = x; L->length+=1 ; return 1 ; } Status Listclear (Sqlist *L) { L->length = 0 ; return 1 ; } Status ListDestory (Sqlist *L) { free(L->elem); L->elem =NULL; L->length = 0 ; L->size = 0 ; } int ListLength (Sqlist L) { return L.length; } Status ListEmpty (Sqlist L) { if (L.length == 0 ) return 1 ; else return 0 ; } Status GetElem (Sqlist L,int i,Elemtype *e) { if (i <= 0 || i >L.length) return 0 ; e = *(L.elem +i -1 ); return 1 ; } Status ListDelete (Sqlist *L,int i,Elemtype *e) { if (i<1 || i> L->length) return 0 ; Elemtype *p = &(L->elem[i-1 ]); e= *p; Elemtype *q = L->elem+L->length-1 ; for (++p; p<=q; p++) { *(p-1 ) = *p; } --L->length; return 1 ; } Status cmp (Elemtype a,Elemtype b) { if (a == b) return 1 ; return 0 ; } int LocateElem (Sqlist L,Elemtype *e, Status (*cmp) (Elemtype,Elemtype) ){ int i = 1 ; Elemtype *p = L.elem; while (i <= L.length && !(*cmp)(*p++,*e)) ++i; if (i < L.length) return i; return 0 ; } void Union_1 (Sqlist *L1,Sqlist L2) { int L1_len = L1->length , L2_len = ListLength(L2); Elemtype *e; for (int i = 1 ; i <= L2.length; i++) { e = L2.elem+i-1 ; if (!LocateElem(*L1,e,cmp)) listinsert(L1,++L1->length,*e); } } void MergeListSq (Sqlist L1,Sqlist L2,Sqlist *L3) { Elemtype *p1 = L1.elem,*p2 = L2.elem; L3->length = L1.length+L2.length; L3->size = L3->length; L3->elem = (Elemtype *)malloc(L3->size*sizeof(Elemtype)); Elemtype *P3 = L3->elem; if (!L3->elem) exit(0 ); Elemtype *p1_e = L1.elem+L1.length-1 ,*p2_e =L2.elem+L2.length-1 ; while (p1 <= p1_e && p2 <= p2_e) { if (*p1 < *p2) *P3++ = *p1++; else *P3++ = *p2++; } while (p1 <= p1_e) *P3++ = *p1++; while (p2 <= p2_e) *P3++ = *p2++; }
可以在main里调用和测试方法;
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 int main () { Sqlist L = initSqlist(); Sqlist L1 = initSqlist(); Sqlist L3 = initSqlist(); int a[5 ] ={1 ,3 ,5 ,7 ,9 }; int b[5 ] = {2 ,4 ,6 ,8 ,10 }; for (int i = 1 ; i <= 5 ; i++) { L.elem[i-1 ] = a[i-1 ]; L.length++; } for (size_t i = 1 ; i <= 5 ; i++) { L1.elem[i-1 ] = b[i-1 ]; L1.length++; } displayTable(L); displayTable(L1); MergeListSq(L,L1,&L3); }
三、链式存储的线性表-单链表 Linklist
3.1 静态链表
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <stdio.h> #define Maxsize 1000 typedef int Elemtype; typedef struct{ Elemtype data; int cur; }node,SlinkList[Maxsize]; int main () { return 0 ; }
3.2 动态链表
1 2 3 4 5 6 7 8 9 #include <stdio.h> typedef int Elemtype; typedef int Status; typedef struct { Elemtype data; struct LNode *next; }LNode,*Linklist;
3.3 方法
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 void List_headInsert (Linklist *L) { LNode *s; Elemtype x; (*L) = (Linklist)malloc(sizeof(LNode)); (*L)->next = NULL; scanf("%d" ,&x); while (x!= 9999 ) { s = (LNode *)malloc(sizeof(LNode)); s->data = x; s->next = (*L)->next; (*L)->next = s; scanf("%d" ,&x); } } void List_tailInsert (Linklist *L) { Elemtype x; (*L) = (Linklist)malloc(sizeof(LNode)); LNode *s,*r = (*L); scanf("%d" ,&x); while (x!=9999 ) { s = (Linklist)malloc(sizeof(LNode)); s->data = x; r->next = s; r = s; scanf("%d" ,&x); } r->next = NULL; } LNode *Getelem_ID(LNode L,int i) { if (i<1 ) return NULL; int j = 1 ; LNode *p = L.next; while (p!= NULL && j < i) { p = p->next; j++; } return p; } LNode *Getelem_V(LNode L,Elemtype x) { LNode *p = L.next; while (p!= NULL && p->data != x) p = p->next; return p; } void showList (LNode L) { Linklist j = L.next; while (j) { printf("%d " ,j->data); j = j->next; } } Status ListInsert_L (Linklist *L,int i,Elemtype x) { Linklist p = *L; int j = 0 ; while ( p && j<i-1 ) { p = p->next; ++j; } if ( !p || j >i-1 ) return 0 ; Linklist s = (Linklist)malloc(sizeof(LNode)); s->data = x; s->next = p->next; p->next = s; return 1 ; } Status ListDelete (Linklist *L,int i,Elemtype *e) { Linklist p = *L; int j = 0 ; while (p->next && j<i-1 ) { p = p->next; j++; } if (!(p->next) || j>i-1 ) return 0 ; Linklist q = p->next; p->next = q->next; *e = q->data; free(q); } void MergeList (Linklist L1,Linklist L2,Linklist *L3) { Linklist p1 = L1->next, p2 = L2->next; Linklist p3 = *L3; p3->next = NULL; while (p1 && p2) { if (p1->data <= p2->data) { p3->next = p1;p3 = p1;p1 = p1->next; } else { p3->next = p2;p3 = p2; p2 = p2->next; } } p3->next = p1 ? p1 : p2; }
测试,运行时输入值,输入9999 时推出插入,采用头差,也可以采用尾插。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int main () { Linklist L; Linklist L1; List_headInsert(&L); Linklist k = L->next; while (k) { printf("%d " ,k->data); k = k->next; } return 0 ; }
四、算法应用
约瑟夫问题
题目:n个人围成一圈,初始编号从1~n排列,从约定编号为x的人开始报数,数到第m个人出圈,接着又从1开始报数,报到第m个数的人又退出圈,以此类推,最后圈内只剩下一个人,这个人就是赢家,求出赢家的编号。
(1)动态链表
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 #include<bits/stdc++.h> struct node{ int data; struct node * next; }; int main () { int n,m; scanf("%d %d" ,&n,&m); node *head,*now,*p,*prev; head = new node ; head->data = 1 ; head->next = NULL; now = head; for (int i = 2 ; i <= n; i++){ p = new node ; p->data = i; p->next = NULL; now->next = p; now = p; } now->next = head; now = head; prev = head; while ((n--)> 1 ){ for (int i = 1 ; i < m; i++){ prev = now; now = now->next; } printf("%d " ,now->data); prev->next = now->next; delete now; now = prev->next; } printf("%d " ,now->data); delete now; return 0 ; }
(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 #include <bits/stdc++.h> const int N = 105 ; struct node{ int id,nextid; }nodes[N]; int main () { int n,m; scanf("%d %d" ,&n,&m); nodes[0 ].id = 0 ;nodes->nextid =1 ; for (int i = 1 ;i <= n; i++){nodes[i].id = i;nodes[i].nextid = i+1 ;} nodes[n].nextid =1 ; int now=1 ;int prve = 1 ; while ((n--) >1 ){ for (int i = 1 ; i < m; i++){ prve = nodes[now].id; now = nodes[now].nextid; } printf("%d " ,nodes[now].id); nodes[prve].nextid = nodes[now].nextid; now = nodes[prve].nextid; } printf("%d " ,nodes[now].id); return 0 ; }
结构体数组双向:
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 #include<bits/stdc++.h> const int N = 105 ; struct node { int id; int preid,nextid; }nodes[N]; int main () { int n,m; scanf("%d %d" ,&n,&m); nodes[0 ].nextid=1 ; for (int i = 1 ; i <= n; i++){ nodes[i].id= i; nodes[i].preid = i-1 ; nodes[i].nextid = i+1 ; } nodes[1 ].preid = n; nodes[n].nextid = 1 ; int now = 1 ; int prev,nextv; while ((n--)>1 ){ for (int i = 1 ; i < m; i++) now = nodes[now].nextid; printf("%d " ,nodes[now].id); prev = nodes[now].preid; nextv = nodes[now].nextid; nodes[prev].nextid = nodes[nextv].id; nodes[nextv].preid = nodes[prev].id; now = nextv; } printf("%d " ,nodes[now].id); return 0 ; }
数组单向链表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include<bits/stdc++.h> int A[150 ];int main () { int n,m; scanf("%d %d" ,&n,&m); for (int i = 1 ; i < n ; i ++) A[i] = i+1 ; A[n] = 1 ; int now = 1 ;int prev = 1 ; while ((n--)>1 ){ for (int i = 1 ;i < m; i++){ prev = now; now = A[now]; } printf("%d " ,now); A[prev] = A[now]; now = A[prev]; } printf("%d " ,now); return 0 ; }
(3)STL list
以后更新博客!
s[now].nextid;
nodes[prev].nextid = nodes[nextv].id;
nodes[nextv].preid = nodes[prev].id;
now = nextv;
}
printf("%d ",nodes[now].id);
return 0;
}
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 数组单向链表: ~~~C++ #include<bits/stdc++.h> int A[150 ];int main () { int n,m; scanf("%d %d" ,&n,&m); for (int i = 1 ; i < n ; i ++) A[i] = i+1 ; A[n] = 1 ; int now = 1 ;int prev = 1 ; while ((n--)>1 ){ for (int i = 1 ;i < m; i++){ prev = now; now = A[now]; } printf("%d " ,now); A[prev] = A[now]; now = A[prev]; } printf("%d " ,now); return 0 ; }
(3)STL list
以后更新博客!