1.定义
a.n个节点离散分配,彼此通过指针相连,
b.每个节点只有一个前驱节点,
c.每个节点只有一个后续节点,
d.首节点没有前驱节点,尾节点没有后续节点。
2.专业术语
首节点:
第一个有效节点
尾节点:
最后一个有效节点
头节点:
头节点的数据类型和首节点的类型一样没有存有效数据,最最前面的,是在首节点之前的,主要是为了方便对链表的操作。
头指针:
(指向头)指向头节点的指针变量(创建一个头结点malloc会返回一个头指针,所有用malloc创建的节点都会返回一个指针)
尾指针:
指向尾节点的指针
(头结点有可能很大,占的内存可能大,假设我想造一个函数输出所有表的值,那你如果不用头指针类型做形参,那由于不同链表的头节点不一样大小,这样就没办法找出形参)
3.确定一个链表需要几个参数?
(或者说如果期望一个函数对链表进行操作我们至少需要接收链表的那些信息?)
只需要一个参数:头指针,因为通过它我们可以推出链表的所有信息。
4.分类
a.单链表
b.双链表:
每一个节点有两个指针域
c.循环链表:
能通过任何一个节点找到其他所有的节点
d.非循环链表
(java中变成垃圾内存则会自动释放,但是C和C++则不会,所以要
手动释放,否则会引起内存泄露。delete等于free)
5.算法
5.0初始化:
注意:这里写跳了第三步
PNODE Create_List(void)
{
int len;//初始化的链表的长度
int val;//要初始化的输入的值
PNODE pHead = (PNODE)malloc(sizeof(NODE));//01创建一个头节点,不存放有效数据为了,方便操作用malloc返回一个头指针pHead
if (NULL == pHead)
{
printf("分配失败!程序终止");
exit(-1);
}
printf("请输入初始化链表节点的个数:len=");
scanf_s("%d", &len);
PNODE pTail = pHead;//02创建一个尾指针,刚开始头指针和尾指针相同,这个尾指针作用是为了方便操作链表。
pTail->pNext = NULL;
for (int i = 0; i < len; i++)
{
printf("请输入第%d个节点的值:",i+1);
scanf_s("%d",&val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("分配失败!程序终止");
exit(-1);
}
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
5.1遍历:
void Traverse_List(PNODE pHead)
{
PNODE pTemp= pHead->pNext;
while (pTemp!=NULL)
{
printf("%d,", pTemp->data);
pTemp = pTemp->pNext;
}
printf("\n");
return;
}
5.2查找:
5.3清空:
5.4销毁:
5.5求长度:
int GetLength_List(PNODE pHead)
{
int length=0;
PNODE p=pHead->pNext;
while (p != NULL)
{
length++;
p = p->pNext;
}
return length;
}
5.6排序:
void Sort_List(PNODE pHead)
{
//----------选择排序------------
PNODE p, q;
int temp;
/*for (p = pHead->pNext; p!= NULL; p=p->pNext)
for (q = p->pNext;q!= NULL;q=q->pNext)
{
if (p->data>=q->data)
{
temp = p->data;
p->data = q->data;
q->data = temp;
}
}*/
//--------冒泡排序----------
int i, j;
for (i = 0,p = pHead->pNext;p != NULL;p = p->pNext,i++)
for (j = 0, q = pHead->pNext;j < GetLength_List(pHead)-i-1;q = q->pNext,j++)
{
if (q->data >= q->pNext->data)
{
temp = q->data;
q->data = q->pNext->data;
q->pNext->data = temp;
}
}
}
5.7删除节点:
bool Delete_List(PNODE pHead, int pos, int *pVal)
{
PNODE p = pHead;
int i = 0;
//p是指向要删除的节点前面的那个节点
while (p->pNext != NULL&&i<pos - 1)//找到pos的节点,p指向其前驱(没看懂,不好理解)
{
i++;
p = p->pNext;
}
if (i>pos || p->pNext == NULL)
{
return false;
}
PNODE q = p->pNext;
*pVal = q->data;
//删除
p->pNext = p->pNext->pNext;
free(q);
q = NULL;
return true;
}
5.8插入节点:
bool Insert_List(PNODE pHead, int pos, int val)
{
PNODE p = pHead;
int i=0;
while (p!=NULL&&i<pos-1)
{
i++;
p = p->pNext;
}
if (i>pos||p==NULL)
{
return false;
}
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("分配空间失败");
exit(-1);
}
pNew->data = val;
pNew->pNext = p->pNext;
p->pNext = pNew;
return true;
}
5.9判断是否为空:
bool Is_Eempty(PNODE pHead)
{
if (pHead->pNext == NULL)
return true;
else
return false;
}
主函数:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node {
int data;
struct Node * pNext;
}*PNODE,NODE;//PNODE相当于struct Node *,NODE相当于struct Node;
PNODE Create_List(void);
void Traverse_List(PNODE pHead);
bool Is_Eempty(PNODE pHead);
int GetLength_List(PNODE pHead);
bool Insert_List(PNODE pHead, int pos, int val);
void Sort_List(PNODE pHead);
bool Delete_List(PNODE pHead, int pos, int *pVal);
int main(void)
{
PNODE pHead =NULL;
pHead = Create_List();
Traverse_List(pHead);
/*int length = GetLength_List(pHead);
printf("该链表的长度为:%d\n",length);*/
//Sort_List(pHead);
//Insert_List(pHead, 2, 66);
int val;
Delete_List(pHead, 2, &val);
printf("删除的元素为:%d\n", val);
Traverse_List(pHead);
system("pause");
return 0;
}
6.链表的优缺点:
优点:
空间没有限制
插入删除元素很快
缺点:
存取速度很慢。
写得很好的关于链表的文章:http://blog.csdn.net/lpp0900320123/article/details/20356143