单链表:
(一):单链表相关知识点理解
单链表是一种链式存取的数据结构。用一组地址任意的存储单元存放线性表中的数据元素。 链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置)。
其中元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
②链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
如下图所示为单链表的存储结构图:
这里每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始结点。 链表由头指针唯一确定,单链表可以用头指针的名字来命名。
终端结点无后继,故终端结点的指针域为空,即NULL。
(二):单链表相关操作
单链表的基本操作包括:建立,初始化,插入,删除,查找,判空,逆置,销毁等,在进行基本操作时 ,需要注意:
1.是否依赖于前驱信息,从而导致初始化值不同。
2.在插入,删除等操作时,应先考虑是否将当前与后面的节点关联起来(以防数据丢失),再关联当前结点与前一个结点。
以下为相关代码块。
//for(p=plist;p->next!=NULL;p=p->next)
//依赖于前驱信息(删除/尾插法/查找前驱信息/查找)
//for(p=plist->next;p!=NULL;p=p->next)
//不需要依赖于前驱信息(打印/获取长度)
typedef struct Node
{
int data; //数据域
struct Node *next; //指针节点(下一个)
}Node,*List; //List li; Node*li;
void InitList(List plist ) //初始化单链表
{
assert(plist!=NULL);
plist->next=NULL;
}
static Node *BuyNode(int val) //申请新的结点
{
Node *p=(Node *)malloc(sizeof(Node));
assert(p!=NULL);
p->data=val;
p->next=NULL;
return p;
}
void Insert_head(List plist,int val) //头插法
{
//Node newnode;
//newnode.data=val;//局部变量,函数结束时,释放(错误申)
Node *p=BuyNode(val);
//plist->next=&newnode;//error
p->next=plist->next;
plist->next=p;
}
void Insert_tail(List plist,int val) //尾插法
{
Node *p;
for(p=plist;p->next!=NULL;p=p->next)
{
;
}//p->next==NULL
/*
for(p=plist->next;p!=NULL;p=p->next)
{
;
}//p==NULL,错误,p=p->plist或许为空
*/
Node *q=BuyNode(val);
p->next=q; //p->next=BuyNode(val);
}
static Node *SearchPri(List plist,int key) //寻找前驱节点
{
Node *p;
for(Node *p=plist;p->next!=NULL;p=p->next)
{
if(p->next->data==key)
{
return p;
}
}
return NULL;
}
bool Delete(List plist,int key) //删除节点
{
Node *p=SearchPri(plist,key);
if(p==NULL)
{
return false;
}
Node *q=p->next;
p->next=q->next;
free(p->next);
}
bool IsEmpty(List p)//判空
{
if(p->next==NULL)
{
return true;
}
return false;
}
void Show(List plist) //打印单链表
{
for(Node *p=plist->next;p!=NULL;p=p->next)
{
printf("% d",p->data);
}
printf("\n");
}
int Getlength(List plist) //获取数据节点的长度,不包括头结点
{
int count=0;
for(Node *p=plist->next;p!=NULL;p=p->next)
{
count++;
}
return count;
}
Node *Search(List plist,int key) //查找节点
{
//for(Node *p=plist;p->next!=NULL;p=p->next),找尾巴
assert(plist!=NULL);
Node *p;
for(p=plist->next;p!=NULL;p=p->next)
{
if(p->data==key)
{
//return p;
break;
}
}
return p;
/*
p=plist->next;
while(p!=NULL && (p->data!=key))//方法2
{
p=p->next;
}
return p;
*/
}
void Destory(List plist)//销毁,以防内存泄漏
{
Node *p;
while(plist->next!=NULL)
{
p=plist->next;
plist->next=p->next;
free(p);
}
}
Node* Reverse(List p) //逆置
{
assert(plist!=NULL);
Node*revhead=NULL;
Node*prev=NULL;
Node*p=plist;
while(p!=NULL)
{
Node*pnext=p->next;
if(pnext==NULL)
{
revhead=p;
}
p->next=prev;
prev=p;
p=pnext;
}
return revhead;
}
以上为单链表的基本相关操作。还需继续完善。