6.离散结构-链表【郝斌数据结构】
离散存储:链表
1.定义:
n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一个后续节点。
首节点没有前驱节点,尾节点没有后续节点。
专业术语:
首节点:第一个有效节点
尾节点:最后一个有效节点
头结点:
头结点的数据类型和首节点类型一样
第一个有效节点之前的那个节点
头结点并不存放有效数据
加头结点的目的主要是为了方便对链表的操作
头指针:指向头结点的指针变量
尾指针:指向尾节点的指针变量
如果希望通过一个函数对链表进行处理,我们至少需要接收链表的哪些参数:
只需要一个参数:头指针,因为我们通过头指针可以推算出链表的其他所有信息
2.分类:
单链表:
双链表:每一个节点有两个指针域
循环链表:能通过任何一个节点找到其他所有结点
非循环链表:
3.算法:
(1)遍历
(2)查找
(3)清空
(4)销毁
(5)求长度
(6)排序
(7)删除节点
删除节点图解:

(8)插入节点
插入节点图解:

算法:狭义的算法是与数据的存数方式密切相关;
广义的算法是与数据的存储方式无关;
泛型:
利用某种技术达到的效果就是:用不同的存数方式,执行的操作是一样的
链表的源程序:
# include <stdio.h> # include <stdlib.h> # include <string.h> typedef struct Node { int data;//数据域 struct Node * pNext;//指针域 }NODE, *PNODE;//NODE等价于struct Node, PNODE等价于struct Node * //函数声明 PNODE create_list(void); void traverse_list(PNODE pHead); bool is_empty(PNODE pHead); int length_list(PNODE pHead); bool insert_list(PNODE pHead, int pos, int val); bool delete_list(PNODE pHead, int pos, int * pval); void sort_list(PNODE pHead); int main(void) { PNODE pHead = NULL;//等价于struct Node * pHead = NULL; int val; //creat_list()功能:创建一个非循环单链表,单链表的头结点地址赋给pHead pHead = create_list(); traverse_list(pHead); if (is_empty(pHead)) printf("列表为空!\n"); else printf("列表不为空!\n"); int len = length_list(pHead); printf("链表的长度为:%d\n", len); sort_list(pHead); traverse_list(pHead); insert_list(pHead, 3, 28); traverse_list(pHead); delete_list(pHead, 4, &val); traverse_list(pHead); return 0; } //创建链表 PNODE create_list(void) { int len;//用来存储有效节点的个数 int i; int val;//用来临时存放用户输入的节点值 //分配了一个不存放有效数据的头结点 PNODE pHead = (PNODE)malloc(sizeof(NODE)); if (NULL == pHead) { printf("分配失败,程序终止!\n"); exit(-1); } PNODE pTail = pHead; pTail->pNext = NULL; printf("请输入你需要生成链表节点的个数:len="); scanf("%d",&len); for (i=0;i<len;++i) { printf("请输入第%d个节点的值:", i+1); scanf("%d", &val); PNODE pNew = (PNODE)malloc(sizeof(NODE)); if (NULL == pNew) { printf("分配失败,程序终止!\n"); exit(-1); } pNew->data = val; pTail->pNext = pNew; pTail = pNew; pTail->pNext = NULL; } return pHead; } //遍历链表 void traverse_list(PNODE pHead) { PNODE p; p = pHead->pNext; while (p != NULL) { printf("%d ", p->data); p = p->pNext; } printf("\n"); return; } //判断列表是否为空 bool is_empty(PNODE pHead) { if (NULL == pHead->pNext) return true; else return false; } //求列表的长度 int length_list(PNODE pHead) { PNODE p = pHead->pNext; int len = 0; while (NULL != p) { ++len; p = p ->pNext; } return len; } //排序 void sort_list(PNODE pHead) { int i, j, t; int len=length_list(pHead); PNODE p, q; for (i=0,p=pHead->pNext; i<len-1; ++i,p=p->pNext) { for(j=i+1,q=p->pNext; j<len; ++j,q=q->pNext) { if(p->data > q->data ) { t = p->data; p->data = q->data; q->data = t; } } } /* 数组的选择排序 int i, j, t; for(i=0;i<len-1; ++i) { for(j=i+1; j<len; ++j) { if (a[i]>a[j]) { t=a[i]; a[i] = a[j]; a[j] = t; } } } */ } //咋pHead所指向链表的第pos个节点的前面插入一个新的节点,该节点的值是val,并且pos值从1开始 bool insert_list(PNODE pHead, int pos, int val) { int i=0; PNODE p = pHead; while(p!=NULL && i<pos-1) { p=p->pNext; ++i; } if (i>pos-1 || NULL==p) return false; PNODE pNew = (PNODE)malloc(sizeof(NODE)); if (NULL == pNew) { printf("动态内存分配失败!\n"); exit(-1); } pNew->data = val; PNODE q = p->pNext; p->pNext=pNew; pNew->pNext=q; return true; } //删除第pos个节点 bool delete_list(PNODE pHead, int pos, int * pval) { int i=0; PNODE p = pHead; while(p->pNext!=NULL && i<pos-1) { p=p->pNext; ++i; } if (i>pos-1 || NULL==p->pNext) return false; PNODE q = p->pNext; *pval = q->data; //删除p节点后面的节点 p->pNext = p->pNext->pNext; free(q); q=NULL; return true; }
4.链表的优缺点:

浙公网安备 33010602011771号