List
Created|Updated
|Post Views:
线性表
线性表是一种逻辑结构,是有序的,所有元素类型相同。
它可以由顺序表和链表(存储结构)来实现。
顺序表
结构:
数组(空间)。ElemType data[MaxSize];
当前长度。int len;
插入,删除
初始化顺序表(顺序表中元素为整型),里边的元素是1,2,3,然后通过scanf读取一个元素(假如插入的是6),插入到第2个位置,打印输出顺序表,每个元素占3个空格,格式为1 6 2 3,然后scanf读取一个整型数,是删除的位置(假如输入为1),然后输出顺序表 6 2 3,假如输入的位置不合法,输出false字符串。
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
| #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #define MaxSize 50 #define ElemType int typedef struct { ElemType data[MaxSize]; int len; } SqList;
void Print(SqList l) { for (int i = 0; i < l.len; i++) { printf("%3d", l.data[i]); } printf("\n"); }
bool Insert(SqList& l, ElemType e, int n) { if (n<1 || n>l.len) { return false; } if (l.len == MaxSize) { return false; } int len = l.len - 1; n = n - 1; for (int i = len; i >= n; i--) { l.data[i + 1] = l.data[i]; } l.data[n] = e; l.len++; return true; }
bool Delete(SqList& l, int n, ElemType &e) { if (n<1 || n>l.len) { return false; } n--; int len = l.len - 1;
e = l.data[n]; for (int i = n; i < len; i++) { l.data[i] = l.data[i + 1]; } l.len--; return true; }
|
链表
链表的大小在程序运行时动态创建。
结构
当前节点数据
指向下一个节点的指针(地址)
头节点(下面的链表都有头节点)
我们只记录链表的头节点地址,称头指针。并且,头节点不存放数据

头插法(逆向建立链表)
头插法需要运用到插入操作。

1 2
| s->next = l->next; l->next = s;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| LinkList Create_List_1(LinkList& l) { l = (LNode*)malloc(sizeof(LNode)); l->next = NULL; LNode* s; ElemType i; scanf("%d", &i); while (i != 9999) { s = (LNode*)malloc(sizeof(LNode)); s->data = i; s->next = l->next; l->next = s; scanf("%d", &i); } return l; }
|
尾插法(正向建立链表)
要新建一个额外的指针,指向尾节点,这样可以不断往后放。最后把尾节点的next==NULL

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| LinkList Create_List_2(LinkList& l) { l = (LNode*)malloc(sizeof(LNode)); l->next = NULL; LNode* s, *r=l; ElemType i; scanf("%d", &i); while (i!=9999) { s = (LNode*)malloc(sizeof(LNode)); s->data = i; r->next = s; r = s; scanf("%d", &i); } r->next = NULL; return l; }
|
查找($$$)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| LinkList GetElem(LinkList l, int i) { LNode* p = l->next; int j = 1;
if (0 == i) { return l; } if (i < 0) { return NULL; } while (p && j < i) { p = p->next; j++; } return p; }
|
插入
要注意的一个点是:原来的链一定要放到最后断开,否则,后面的节点就找不到了。
1 2 3 4 5 6 7 8 9 10 11 12
| bool FrontInsert(LinkList l,ElemType e, int i) { LNode* s = (LNode*)malloc(sizeof(LNode)); s->data = e; LNode *p=GetElem(l, i-1); if (NULL == p) { return false; } s->next = p->next; p->next = s; return true; }
|
删除
1 2 3 4 5 6 7 8 9 10 11 12 13
| bool Delete(LinkList l, int i) { LNode* p = GetElem(l, i-1); if (NULL == p) { return false; } LNode* s = p->next; p->next = s->next; free(s); s = NULL; return true; }
|
双向链表
1 2 3 4 5
| typedef struct DNode { ElemType data; struct DNode* prior; struct DNode* next; }DNode, * DLinkList;
|
头插法(逆向建立链表)
原来的链一定要放到最后断开,否则,后面的节点就找不到了。
判断dl->next不为空时,才让下一个节点的prior指向新节点if (dl->next){dl->next->prior = s;}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| DLinkList Dlist_head_insert(DLinkList& dl) { dl = (DNode*)malloc(sizeof(DNode)); dl->prior = dl->next = NULL; ElemType e; scanf("%d", &e); while (e != 9999) { DNode* s = (DNode*)malloc(sizeof(DNode)); s->data = e; s->next = dl->next; s->prior = dl; if (dl->next) { dl->next->prior = s; } dl->next = s; scanf("%d", &e); } return dl; }
|
Tips
当我们遇到序号从0开始,和序号从1开始时,我们怎么把他们变成相同的序号。
我们可以把将从1开始的全部序号-1,那么从1开始的序号就变成了从0开始。
or
把将从0开始的全部序号+1,那么从0开始的序号就变成了从1开始。
数据结构的基本操作
所有的数据结构的基本操作都大致相同,都是4种。增,删,改,查