一、定义--离散存储【链表】
n个节点离散分配;彼此通过指针相连;每个节点只有一个前驱节点,
每个节点只有一个后续节点;首节点没有前驱节点,尾节点没有后续节点。
二、专业术语:
首节点:第一个有效节点
尾节点:最后一个有效节点
头节点:第一个有效节点前面的那个节点;头节点不存放有效数据;
加上头节点是为了方便对链表的操作
头指针:指向头节点的指针变量
尾指针:指向尾节点的指针变量
三、分类:单链表;双链表;循环链表;非循环链表
四、代码
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct node{
int data; //数据域
struct node * pNext; //指针域
}NODE,* PNODE; //NODE等价于struct node;PNODE等价于 struct node *
PNODE init_link(void);
void traverse_link(PNODE pHead);
bool is_empty(PNODE pHead);
int length_link(PNODE pHead);
bool insert_link(PNODE pHead,int pos,int val);
bool del_link(PNODE pHead,int pos,int * val);
bool sort_link(PNODE pHead);
int main(void)
{
//首先创建头节点
PNODE pHead = NULL; //一个指针只需一个参数,即头节点即可确定下来。
int val;
int * pVal = &val; //用来接收删除的节点数据
pHead = init_link();
if(is_empty(pHead))
{
printf("数组为空。。。\n");
}else{
printf("数组不为空。。。\n");
}
printf("数组长度为:%d\n",length_link(pHead));
traverse_link(pHead);
insert_link(pHead,3,333);
traverse_link(pHead);
if(del_link(pHead,4,pVal))
{
printf("链表节点删除成功,你删除的节点数据是:%d 。\n",*pVal);
}else{
printf("链表节点删除失败!");
}
sort_link(pHead);
traverse_link(pHead);
return 0;
}
PNODE init_link(void)
{
int i;
int len; //链表有效长度
int val; //临时存放用户数据
printf("请输入链表有效长度:len= ");
scanf("%d",&len);
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if(pHead == NULL)
{
printf("内存分配失败,程序终止\n");
exit(-1);
}
PNODE pTail = pHead; //设置一个尾指针,永远指向尾节点,方便新节点pNew挂在后面
pTail->pNext = NULL;
for(i=0;i<len;i++)
{
printf("请输入第 %d 个节点的值:",i+1);
scanf("%d",&val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(pNew == NULL)
{
printf("内存分配失败,程序终止\n");
exit(-1);
}
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
void traverse_link(PNODE pHead)
{
PNODE p = pHead->pNext; //第一个有效节点
while(p!=NULL)
{
printf("%d ",p->data);
p = p->pNext;
}
printf("\n");
}
bool is_empty(PNODE pHead)
{
PNODE p = pHead->pNext;
if(p==NULL)
return true;
else
return false;
}
int length_link(PNODE pHead)
{
int cnt=0;
PNODE p = pHead->pNext;
while(p!=NULL)
{
cnt++;
p = p->pNext;
}
return cnt;
}
bool insert_link(PNODE pHead,int pos,int val)
{
int i=0;
PNODE p = pHead;
while(p!=NULL && i<pos-1)
{
p = p->pNext;
i++;
}
if(p==NULL || i>pos-1)
return false;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(pNew==NULL)
{
printf("动态内存分配失败!\n");
exit(-1);
}
pNew->data = val;
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return true;
}
bool del_link(PNODE pHead,int pos,int * pVal)
{
int i=0;
PNODE p = pHead;
while(p->pNext!=NULL && i<pos-1)
{
p = p->pNext;
i++;
} //经过while循环,p此时指向pos位置前面那个节点
if(p->pNext==NULL || i>pos-1)
return false;
PNODE q = p->pNext; //q即为pos位置处的节点
*pVal = q->data;
//删除pos位置的节点
p->pNext = p->pNext->pNext;
free(q); //释放内存,防止内存泄漏。
q = NULL;
return true;
}
/*
何为算法:
狭义的算法是与数据的存储方式密切相关的;
广义的算法是与数据的存储方式无关的;
泛型:
利用某种技术达到的效果就是:针对不同的存储方式,执行的操作是一样的
*/
bool sort_link(PNODE pHead)
{
int i,j,temp; //数组中定义的参量
PNODE p,q; //链表中定义的参量
for(i=0,p = pHead->pNext;i<length_link(pHead)-1;i++,p=p->pNext)
for(j=i+1,q=p->pNext;j<length_link(pHead);j++,q=q->pNext)
if(p->data<q->data) //等价于a[i]<a[j]
{
temp = q->data; //等价于a[i] = a[j];
q->data = p->data; //a[j] = a[i];
p->data = temp; //a[i] = temp;
}
}
运行结果:

五、数组与链表优缺点对比
数组(元素类型相同,大小相等):
优点:存取速度很快;
缺点:插入删除速度很慢;空间通常有限制;事先需要知道数组长度;需要大块内存块
链表:
优点;空间没有限制;插入删除元素很快
缺点:存取速度慢
来源:https://www.cnblogs.com/ljd4you/p/9507241.html