链表简介
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
相比于线性表顺序结构在插入的时候可以达到O(1)的复杂度,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间.同时失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
链表有很多种不同的类型:单向链表,双向链表以及循环链表。
单链表
单链表中每个结点只包含一个数据域和一个指针.
单链表声明
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
| typedef int T;
typedef struct link{ T data; struct link *next; }SingleLinkList, *PSingleLinkList;
PSingleLinkList Init();
int isEmpty(PSingleLinkList p);
void clearList(PSingleLinkList head);
int length(PSingleLinkList head);
PSingleLinkList append(PSingleLinkList tail, T data);
int insertT(PSingleLinkList head, int pos, T data);
int deleteT(PSingleLinkList head, int pos, T data);
T getValue(PSingleLinkList head, int pos);
int getPos(PSingleLinkList head, T data);
void printSingleList(PSingleLinkList head);
|
单链表的初始化
链表初始化时生成一个空结点,指针指向这个空结点.
这个空结点不存储数据,只为了在判断边界时更加方便.初始化完成后返回这个结点的头指针.
1 2 3 4 5 6
| PSingleLinkList Init(){ PSingleLinkList head; head = (PSingleLinkList)malloc(sizeof(SingleLinkList)); head->next = NULL; return head; }
|
判断链表是否为空
只要头结点的后继指针不为空则链表不为空
1 2 3 4 5 6 7
| int isEmpty(PSingleLinkList p){ if(p->next != NULL){ return 0; } return 1; }
|
清空链表
清空链表时需要释放对应的内存,顺序是从头结点开始依次释放内存直到指针为空为止.最后再将头指针的后继指针设为空.
释放内存需要两个指针,tmp指针指向要释放的内存位置,next指针指向下一个要释放内存的位置.
1 2 3 4 5 6 7 8 9 10 11
| void clearList(PSingleLinkList head){ PSingleLinkList tmp, next; tmp = head->next; while(tmp != NULL){ next = tmp->next; free(tmp); tmp = next; } head->next = NULL; }
|
返回链表长度
1 2 3 4 5 6 7 8 9 10
| int length(PSingleLinkList head){ int i = 0; head = head->next; while(head != NULL){ head = head->next; i++; } return i; }
|
尾插
在链表尾部插入一个数据
1 2 3 4 5 6 7 8 9 10 11
| PSingleLinkList append(PSingleLinkList tail, T data){
PSingleLinkList tmp; tmp = (PSingleLinkList)malloc(sizeof(SingleLinkList)); if(tmp == NULL){return NULL;} tail->next = tmp; tmp->data = data; tmp->next = NULL; tail = tmp; return tail; }
|
插入数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int insertT(PSingleLinkList head, int pos, T data){ PSingleLinkList tmp; if(posIsRight(head, pos) == -1){ return -1; } for(int i=0; i<pos; i++){ head = head->next; } tmp = (PSingleLinkList)malloc(sizeof(SingleLinkList)); tmp->data = data; tmp->next = head->next; head->next = tmp; return 1; }
|
删除数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| int deleteT(PSingleLinkList head, int pos, T data){ PSingleLinkList tmp; if(posIsRight(head, pos) == -1){ return -1; } for(int i=0; i<pos; i++){ head = head->next; } tmp = head->next; head->next = head->next->next; free(tmp); return 1;
}
|
获取固定位置的数据
1 2 3 4 5 6 7 8 9 10 11
| T getValue(PSingleLinkList head, int pos){ if(posIsRight(head, pos) == -1){ return -1; } for(int i=0; i<pos; i++){ head = head->next; } head = head->next; return head->data; }
|
获取数据的位置
1 2 3 4 5 6 7 8 9 10
| int getPos(PSingleLinkList head, T data){ int len = length(head); for(int i=0; i<len; i++){ head = head->next; if(head->data == data){ return i; } } return -1; }
|
打印链表
1 2 3 4 5 6
| void printSingleList(PSingleLinkList head){ while(head->next != NULL){ head = head->next; printf("%d\n", head->data); } }
|
双向链表
循环链表