数据结构术语
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
| 结构是指数据间的关系
数据结构是指 相互之间存在某种特定关系的数据元素的集合
数据结构包括三方面 数据的逻辑结构 数据的存储结构 数据的运算 一个算法的设计取决于选定的逻辑结构,算法的实现依赖于采用的存储结构 线性 一对一 树状 一对多 网状 多对多
数据结构是一个二元组 (D,R), D是数据元素的有限集, R是D上关系的有限集
数据结构的5个重要特性 (算法的特征) 有穷性 确定性 可行性 输入, 输出
算法要求 可读性 健壮性 效率与储存需求
时间复杂度排序 O(1) < O(log₂n) < O(n) < O(n*log₂n ) < O(n2)< O(n3)…<O(2n)<O(3n)<…<O(n!)
|
顺序线性表
0.线性表类型定义
1. 顺序表定义
1 2 3 4 5
| typedef struct { char data[max]; //数据(数组) int length; //长度 }sqlist,L //结构体名
|
1 2 3 4 5 6 7
| 读取表里面的数据 int A; A = sqlist.data[i];
读取表长 int lenght; length = sqlist.length;
|
2. 顺序表相关操作
初始化
1 2 3
| void initList(SqList &L){ L.length = 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
| int sqLiistInsert(sqlist &L, int i, char e){ if(i<1||i>L.length){ return -1; } if(L.length>=L.size){ ...... } char *p, *q; q = &(L.elem[i-1]); for(p = &(L.data[L.length-1]), p>=q; p--){ *(p+1) = *p; } *q = e; L.length++; return 0; }
|
1 2 3 4 5
| for(i = L.length - 1, i >= p, i--){ L.data[i+1] = L.data[i]; } L.data[p] = e;
|
插入时间复杂度
删除数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int delete(Sqlist &L, int x, int *y){ int j; if(x<1 || x>Llength){ return -1; } else{ *y = L.data[i-1]; for(j=x; j<=Length-1; j++){ L.data[j-1] = L.data[j]; } L.length--; } }
|
删除时间复杂度
按值查找
1 2 3 4 5 6 7 8
| int finddata(Sqlist &L, int e){ int i; for(i =0; i < L.length; i++){ if(e == L.data[i]) return 0; } return -1; }
|
无序表合并
1 2 3 4 5 6 7 8 9 10 11 12 13
| void mergelist(list la, list lb, list &lc){ initlist(lc) int i = 1, j = 1, k = 0; la_len = listlength(la); lb_len = listlength(lb); for(i = 1; i < lb_len; i++){ e = listget(lb,i) if(!listlocal(la, e)){ listinsert(la,++la_len, e) } } }
|
缺点
1 2 3
| 1. 插入和删除操作时需要移动大量元素。 2. 要给长度变化较大的线性表预先分配空间,利用率不好。 3. 表的容量难以扩充
|
链表
特点: 用一组任意的存储单元存储线性表的数据元素(可连续可不连续)
单链表
定义
1 2 3 4 5
| typedef struct Lnode { int data; Struct Lnode *next; }Lnode,*linklist;
|
取用data
1 2 3
| Lnode S; int b; b = S -> data;
|
取第i
个元素
1 2 3 4 5 6 7 8 9 10 11 12
| Linklist ListGet(linklist L,int i) { p=L->next; j=1; While(p&&j<i){ p=p->next;++j; } If(!p||j>i) return error; e=p->data; Return OK; }
|
插入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Linklist listinsert_L(linklist L,int i, elemtype e){ p = L; j = 0; While(p&&j<i-1){ p = p->next; ++j; } if (!p||j>i-1) return error; s = (linklist)malloc(sizeof(Lnode)); s->data = e; s->next = p->next; p->next = s; Return ok; }
|
删除
1 2 3 4 5
| 与插入不同的部分 q = p->next; p->next = q->next; e = q->data; free(q);
|
插入删除时间复杂度
尾插法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Linklist linklistcreate(){ Linklist L; L=(Lnode*)malloc(sizeof(Lnode)); L->next=NULL; r=L; scanf(&x); while(x!=flag){ s=(Lnode*)malloc(sizeof(Lnode)); S->data=x; s->next=NULL; r->next=s; r=s; Scanf(&x); } Return L; }
|
头插法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Linklist linklistcreate() { Linklist L; L=(Lnode*)malloc(sizeof(Lnode)); L->next=NULL; scanf(&x); while(x!=flag) {s=(Lnode*)malloc(sizeof(Lnode)); S->data=x; s->next=NULL; s->next=L->next; L->next=s; scanf(&x); } return L; }
|
合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc) { pa=La->next; pb=Lb->next; Lc=pc=La; while(pa&&pb) { if(pa->data <= pb->data) { pc->next=pa; pc=pa; pa=pa->next; } else { pc->next=pb; pc=pb; pb=pb->next; } } pc->next=pa?pa:pb; free(Lb); }
|
循环链表
循环条件不是P或P->next是否为空,而是P->next=H
只剩两个个元素
1 2 3 4
| q=L->next; p->data=q->data; L->next=q->next; free(q);
|
不是最后两个元素
1 2 3 4
| q=p->next; p->data=q->data; p->next=q->next; free(q);
|
合并循环链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| LinkList merge(LinkList LA, LinkList LB) { linklist *p, *q; p=LA; q=LB; while(p->next! =LA) p=p->next; while(q->next! =LB) q=q->next; q->next=LA; p->next=LB->next; free(LB); return(LA); }
|
双向链表
插入
1 2 3 4
| s->prior = p->prior; p->prior->next = s; s->next = p; p->prior = s;
|
栈和队列