一、单链表
单链表,就是线性表的链式存储结构,又称线性链表。
它的特点是:用一组任意的存储单元存储线性表的数据元素,即结点之间在逻辑上是连续的,在物理上是不连续的。
单链表是带有头结点的,头节点只起到“哨兵”的作用,它的数据域是不使用的,指针域指向第一个数据域的位置。
以下代码是单链表各个结点的逻辑表示:data是节点的数据域,next是指针域——存储下一个结点的地址。
typedef struct Node
{
int data;
Node *next;
}Node,*List;
见下图:
二、单链表的相关操作
一共十二种常用操作,头文件声明见下:
//1.初始化
void InitList(List plist);
//2.头插
bool Insert_head(List plist, int key);
//3.尾插
bool Insert_tail(List plist, int key);
//4.查找
Node *Search(List plist, int key);
//5.删除数据结点
bool Delete(List plist, int key);
//6.得到单链表的长度,不包括头结点
int Getlength(List plist);
//7.判断单链表是否为空
bool IsEmpty(List plist);
//8.打印单链表的数据
void Show(List plist);
//9.清空链表
void clear(List plist);
//10.摧毁单链表的数据(释放数据结点)
void Destroy(List plist);
//11.得到pos位置的数据
bool GetElem(List plist, int pos, int key);
//12.逆置
void Reverse(List plist);
//13.取出重复的值
void Unique(List plist);
1. 初始化 void InitList(List plist);
void InitList(List plist)
{
assert(plist!=NULL);
if(plist==NULL)
{
return ;
}
plist->next = NULL;
}
初始化一个单链表,就是把头结点的next置空,即没有一个数据结点。
2.头插
bool Insert_head(List plist, int key);
{
assert(plist!=NULL);
if(plist==NULL)
{
return false;
}
Node *p = (Node*)malloc(sizeof(Node));//利用动态内存 新创建一个节点
p->data = key;//将数据存入新结点的数据域
p->next = plist->next;//先把后面的结点牵住
plist->next = p;//头结点把插入的点牵住
return true;
}
头插法,即在头结点后面插入新的节点,我们需要解决的问题是:如何将新的结点与它的前驱(头结点)、后继联系在一块?
我们不妨换个角度思考,一排的人手拉手,第一个人的后面要插进来一个人,第一个人肯定要先将后面的人交到新人的手里,再把新人牵住,才不会把后面的人丢掉。见下图:
头插法的具体过程:
三、尾插
bool Insert_tail(List plist, int key)//插入的结点变为新的尾结点
{
assert(plist!=NULL);
if(plist==NULL)
{
return false;
}
Node