目录
8补充.在一个无头单链表中的某一个结点的前面插入一个值x,如何插入(不知道头指针)
0.结点以及单链表的空间开辟
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLTNode;
LTNode* BuySLNode(SLTDataType x)
{
SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode);
node->data = x;
node->next = NULL;
return node;
}
1.打印链表
void SListPrint(SLTNode* plist)
{
SLTNode* cur = plist;
while (cur != NULL)
{
printf("%d ", cur->data);
cur = cur->next;//赋值下一个结点的地址,即指向下一个结点
}
printf("\n");
}
2.尾插法
LTNode* BuySLNode(SLTDataType x)
{
SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode);
node->data = x;
node->next = NULL;
return node;
}
void SListPushBack(SLTNode* plist, SLTDataType x)
{
//先遍历找尾
SLTNode* tail = plist;
while (tail->next != NULL)
{
tail = tail->next;
}
SListNode* newnode = BuySLTNode(x);
tail->next = newnode;
}
上述尾插法存在问题:空表时出现问题
改正如下,还是出现空
void SListPushBack(SLTNode* plist, SLTDataType x)
{
SLTNode* newnode = BuySLTNode(x);
//1空
//2非空
if (plist == NULL)
{
plist = newnode;
}
else
{
//遍历找尾
SLTNode* tail = plist;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
TestSList1()函数和SListPushBack()函数建立不同的栈帧。其中结点x出现在堆上
改正如下:加入二级指针,TestSList1()函数中加入&
void SListPushBack(SLTNode**pplist, SLTDataType);
void SListPushBack(SLTNode** pplist, SLTDataType x)
{
SLTNode* newnode = BuySLTNode(x);
//1空
//2非空
if (*pplist == NULL)
{
*pplist = newnode;
}
else
{
//遍历找尾
SLTNode* tail = *pplist;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
3.头插法
void SListPushFront(SLTNode** pplist, SLTDataType x)
{
SLTNode* newnode = BuySLTNode(x);
newnode->next = *pplist;
*pplist = newnode;
}
链表为空的时候情况如下,即头插法不考虑链表为空的情况
4.尾删法
若代码如下,出现问题
void SListPopBack(SLTNode* plist)
{
SLTNode* tail = plist;
while (tail->next != NULL)
{
tail = tail->next;
}
free(tail);
tail = NULL;
}
删除最后一个结点后还应把前一个结点的next域置空
void SListPopBack(SLTNode* plist)
{
SLTNode* prev = NULL;
SLTNode* tail = plist;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
若出现下面两种情况时仍有问题:前者tail为空指针,不进入while循环,后者tail不等于空但是tail的next域为空,且prev为空
void SListPopBack(SLTNode**pplist)
{
//1.没有结点
//2.一个结点
//3.多个结点
if (*pplist = NULL)
{
return;
}
else if((*pplist)->next == NULL)
{
free(*pplist);
*pplist = NULL;
}
else
{
SLTNode* prev = NULL;
SLTNode* tail = *pplist;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
5.头删法
void SListPopFront(SLTNode**pplist)
{
if(*pplist = NULL)
{
return;
}
else
{
SLTNode* next = (*pplist)->next;
free(*pplist);
*pplist = next;
}
}
若只有一个结点
6.单链表的查找
SLTNode* SListFind(SLTNode* plist, SLTDataType x)
{
SLTNode* cur = plist;
//while(cur!=NULL)
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
7.单链表的插入
单链表在Pos位置之后插入x
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* newnode = BuySLTNode(x);
pos->next = newnode;
newnode->next = pos->next;
}
上述代码导致d3地址丢失,改正如下
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* newnode = BuySLTNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
单链表在pos位置之前插入x(难点在于找pos的前一个结点,需要从头开始找)
void SListInsert(SLTNode*plist, SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* newnode = BuySLTNode(x);
SLTNode* prev = NULL;
SLTNode* cur = plist;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
prev->next = newnode;
newnode->next = pos;
}
若pos为第一个的时候
改正如下
void SListInsert(SLTNode**pplist, SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* newnode = BuySLTNode(x);
if (pos == *pplist)//头插
{
newnode->next = pos;
*pplist = newnode;
}
else
{
SLTNode* prev = NULL;
SLTNode* cur = *pplist;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
prev->next = newnode;
newnode->next = pos;
}
}
8补充.在一个无头单链表中的某一个结点的前面插入一个值x,如何插入(不知道头指针)
后插一个值为x的结点,然后跟后面的节点值(data值)交换
9.单链表的删除
9.1删后一个位置:存在两种情况
void SListEraseAfter(SLTNode* pos)
{
assert(pos);
if (pos->next == NULL)
{
return;
}
else
{
SLTNode* next = pos->next;
pos->next = next->next;
free(next);
}
}
9.2 删除当前位置
面临的问题:找pos位置的前一个->相当于头删->传二级指针
void SListEraseCur(SLTNode*plist,SLTNode*pos);