链表
链表的概念及结构
概念:链表是一种物理存储结构上非连续,非顺序的储存结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
注意:
1.从上图可以看出,链式结构在逻辑上是连续的,但是在物理上不一定连续。
2.现实中的节点一般都是从堆上申请出来的。
3.从堆上申请的空间,是按照一定的策略来分配的,再次申请的空间可能连续,也可能不连续。
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDAtaType;
typedef struct SListNode
struct SListNode
{
int datd;
struct SListNode* next;
}SLTNode;//定义结构体
#include "SList.h"
void TestSList1()//创建一个四个数据的链表
{
SLTNode* n1=malloc(sizeof(SLTNode));
assert(n1);
SLTNode* n2=malloc(sizeof(SLTNode));
assert(n2);
SLTNode* n3=malloc(sizeof(SLTNode));
assert(n3);
SLTNode* n4=malloc(sizeof(SLTNode));
assert(n4);
n1->data=1;
n2->data=2;
n3->data=3;
n4->data=4;//创建节点
n1->next=n2;
n2->next=n3;
n3->next=n4;
n4->next=NULL;
}
int main()
{
return 0;
}
上一个节点存储下一个节点的地址。
打印链表
#include "SList.h"
void SListPrint(SLTNode* phead)
{
SListNode* cur=phead;
while(cur !=NULL)
{
printf("%d->",cur->data);
cur =cur->next;
}
printf("NULL\n);
}
cur->next;//结构体访问 (定义结构体)
链表的分类
1.单向或者双向
2.带头或者不带头
3.循环或不循环
1.无头单向非循环链表:结构简单,一般不会单独用来存数据,实际中更多是作为其他数据结构的子结构
2.带头双向循环链表:结构最复杂,一般用在单独存储数据
尾插
头文件void SListPushback(SLTNode* phead,SLTDataType x)
;
源文件
void SListPushBack(SLTNode** pphead,SLTDataType x)
{
SLTNode* newnode =(SLTNode*)malloc(sizeof(SLTNode));
assert(newnode);
newnode->data =x;
newnode->next = NULL;
if (*pphead==NULL)
{
*pphead=newnode;
}
else
{
//找尾节点
SListNode*tail = *pphead;
while(tail->next !=NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
void TestSList2()//创建一个四个数据的链表
{
SLTNode* plist=NULL;
SListPushBack(&plist,5);
SListPushBack(&plist,6);
SListPushBack(&plist,7);
SListPushBack(&plist,8);
SListPushBack(&plist,9);
SlistPrint(plist);
}
头插
void SlistPushFront(SLTNode** pphead,SLTDataType x)
{
SLTNode* newnode =(SLTNode*)malloc(sizeof(SLTNode));
assert(newnode);
newnode->data =x;
newnode->next = NULL;
newnode->next=*pphead;
*pphead=newnode;
}
void TestSlist2()
{
SLTNode* list=NULL;
SLIstPushFront(&plist,0);
SListPrint(plist);
}
头删
void SListPopFront(SLTNode** pphead)
{
//assert(*pphead!=NULL);
if(*pphead==NULL)
return;
SLTNode* next=(*pphad)->next;
free(**phead);
*pphead=next;
}
尾删
void SListPopBack(SLTNode** pphead)
{
assert(*pphead);
//只有一个节点 多个节点
if((*pphead)->next==NULL)
{
free(*pphead);
*pphead=NULL;
}
else{
/*
SLTNode* tailPrev=NULL;
SLTNode* tail=*pphead;
while(tail->next!=NULL)
{
tailPrev=tail;
tail=tail->next;
}
free(tail);
tailPrev->next=NULL;*/
SLTNode* tail=*pphead;
while(tail->next->next!=NULL)
{
tail=tail->next;
}
free(tail->next);
tail->next=NULL;
}
]
查找
SLTNode* SListFind(SLTNode* phead,SLTDataType x)
[
SLTNode* cur=phead;
while(cur)
{
if(cur->data=x)
return cur;
cur
}
void TestSList()
{
SLTNode* plist=NULL;
SListPushBack(&plist,1);
SListPushBack(&plist,2);
SListPushBack(&plist,3);
SListPushBack(&plist,4);
SListPushBack(&plist,5);
SLTNode* ret=SListFind(plist,3);
if(ret)
{
printf("找到了");
ret->data=30;
}
SListPrint(plist);
}
在pos位置之前插入
void SListInsert(SLTNode** pphead,SLTNode* pos,SLTDataTyps x)
{
assert(pos);
assert(pphead);
//头插
if(pos==*pphead)
{
SListPushFront(pphead,x);
}
else
{
SLTNode* prev=*pphead;
while(prev->next !=pos)
{
prev=prev->next;
}
SLTNode* newnode=BuySListNode(X);
//BuySListNode(X);
prev->next=newnode;
newnode->next=pos;
}
}
删除pos位置的值
void SListErase(SLTNode** pphead,SLTNode* pos)
{
assert(pphead);
assert(pos);
if(*pphead==pos)
{
SListPopFront(pphead);
}
else
{
SLTnode* prev=*pphead;
while(prev->next !=pos)
{
prev=prev->next;
}
prev->next=pos->next;
free(pos);
}
}
单链表删除pos位置之后插入x
void SListInsertAfter(SLTNode* pos,SLTDataTyps x)
{
assert(pos);
/*SLTNode* newnode=BuySListNode(x);
newnode->next=pos->next;
pos->next=newnode;*/
//不在乎链接顺序
SLTNode*newnoed=BuySListNode(x);
SLTNide next=pos->nexy;
//pos newnode next
}