单链表以及其基本操作

链表以及基本操作

1. 链表是一种链式存储的线性表,每个存储单元称为结点

链表是相互连接起来的存储单元,一个存储单元包含两部分

一部分表示的是指向下一个存储单元的指针,另一部分表示的是的存储单元中的数据元素。

2. 接下来就进行一些基本的链表操作

1)链表的建立

//链表类型在头文件中的定义

 

typedef int DataType;

typedef struct SListNode

{

DataType _data;

struct SListNode* _pNext; // 指向下一个结点的指针

}Node, *PNode;

 

 

//开辟空间,并初始化

PNode BuySListNode(DataType data)

{

PNode node = (Node*)malloc(sizeof(Node));//开辟一个Node类型的结点的空间

node->_data = data;

node->_pNext = NULL;

return node;

}

// 尾插

void SListPushBack(PNode*ppHead, DataType data)

{

assert(ppHead);

if (NULL == *ppHead)

{

*ppHead = BuySListNode(data);

}

else

{

PNode pTail = *ppHead;

while (pTail->_pNext)

{

pTail = pTail->_pNext;

}

pTail->_pNext = BuySListNode(data);

}

}

// 头插

void SListPushFront(PNode* ppHead, DataType data)

{

assert(ppHead);

PNode pnewnode = BuySListNode(data);//创建一个新的头结点

pnewnode->_pNext = *ppHead;//更新头结点

*ppHead = pnewnode;

}

 

 

 

(2) 链表的特殊位置以及指定位置的插入和删除

 

// 尾删

void SListPopBack(PNode* ppHead)

{

assert(ppHead);

PNode pTail = *ppHead;

PNode pre = NULL;

while (pTail == NULL)//为空时,直接返回

{

printf("链表为空");

return;

}

if (pTail->_pNext == NULL)//有一个结点时,释放掉一个结点

{

free(pTail);

pTail = NULL;

}

else if (pTail->_pNext)//为多个时,借用pre来更新链表

{

pre = pTail;

pTail->_pNext = pTail;

}

free(pTail);

pre->_pNext = NULL;

}

// 头删

void SListPopFront(PNode* ppHead)

{

assert(ppHead);

while (*ppHead == NULL)

{

printf("链表为空");

return;

}

PNode pdel = *ppHead;//pdel指向头结点

*ppHead = pdel->_pNext;//改变头结点的位置

free(pdel);

}

// data插入在pos之前

void SListInsert(PNode* ppHead, PNode pos, DataType data)//  1  2  3(5)  4-------》pos为4,data为5

{                                                                  

assert(ppHead);

PNode pcur = *ppHead;

PNode pnewnode = BuySListNode(data);

if (pcur== pos)//当pos为头结点时

{

SListPushFront(ppHead, data);//头插

    }

if (pcur->_pNext != pos)//后移

{

pcur = pcur->_pNext;

}

else

{

pcur->_pNext = pnewnode;//3指向5

pnewnode->_pNext = pos;//5指向4

    }

}

// 删除链表中pos位置的结点

void SListErase(PNode* ppHead, PNode pos)//    1   2   3   4---->删除pos为3的结点

{

assert(ppHead);

PNode pcur = *ppHead;

PNode pre = *ppHead;

if(pcur==NULL||pos==NULL)

{

printf("无法删除");

}

if (pcur == pos)//当pos为头结点时

{

SListPopFront(ppHead);//头删

}

else

{

PNode pre = *ppHead;

while (pre&&pre->_pNext != pos)

{

pre = pre->_pNext;

}

if (pre)

{

   pre->_pNext = pos->_pNext;//更新链表

    }

free(pos);

}

(3)其余的操作

// 在链表中查找元素data,返回该结点在链表中的位置

PNode Find(PNode pHead, DataType data)

{

assert(pHead);

PNode pcur = pHead;

while (pcur)

{

if (pcur->_data == data)

{

return pcur;

}

pcur = pcur->_pNext;

}

return NULL;

}

// 获取链表中结点的个数

int Size(PNode pHead)

{

PNode pcur = pHead;

assert(pHead);

int count;

while (pcur)

{

count++;

pcur = pcur->p_Next;

        }

return count;

}

// 判断链表是否为空,若为空,返回true,否则返回false

size_t Empty(PNode pHead)

{

assert(pHead);

if (pHead == NULL)

{

return 1;

}

else

return 0;

}

// 销毁单链表

void SListDestroy(PNode * ppHead)

{

assert(ppHead);

PNode pre = NULL;//用于更新链表

PNode pcur = *ppHead;

while (pcur)

{

pre = pcur;

pcur->_pNext = pcur;

}

free(pcur);

free(pre);

}

// 打印单链表

void SListPrint(PNode pHead)

{

assert(pHead);

PNode pcur = pHead;

while (pcur)

{

printf("->%d", pcur->_data);

}

printf("\n");

}

3. 测试函数

#include "linklist.h"

int main()

{

Node* L=NULL;//L为指向链表的指针

Node *pos = L;//pos为二级指针

pos = pos->_pNext;

BuySListNode(0);

SListPushBack(&L, 1);//需要传指针的地址,因为需要对链表会有内容的改变

SListPushBack(&L, 2);

SListPushBack(&L, 3);

SListPushBack(&L, 4);

SListPushBack(&L, 5);

SListPrint(&L);

SListPopBack(&L);

SListPrint(&L);

SListPushFront(&L, 0);

SListPrint(&L);

SListPopFront(&L);

// 在链表中查找元素data,返回该结点在链表中的位置

Find(&L, 3);

// data插入在pos之前

SListInsert(&L, pos, 8);

SListPrint(&L);

SListErase(&L, pos);

SListPrint(L);

// 获取链表中结点的个数

Size(L);

// 判断链表是否为空,若为空,返回true,否则返回false

Empty(L);

// 销毁单链表

SListDestroy(&L);

system("pause");

return 0;

}

4.头文件

#include"stdio.h"

#include"assert.h"

#include"windows.h"

#ifndef _LINKLIST_H__

#define _LINKLIST_H__

//链表类型在头文件中的定义

typedef int DataType;

typedef struct SListNode

{

DataType _data;

struct SListNode* _pNext; // 指向下一个结点的指针

}Node, *PNode;

// 尾插

void SListPushBack(PNode*ppHead, DataType data);

// 尾删

void SListPopBack(PNode* ppHead);

// 头插

void SListPushFront(PNode*ppHead, DataType data);

// 头删

void SListPopFront(PNode* ppHead);

// 在链表中查找元素data,返回该结点在链表中的位置

PNode Find(PNode pHead, DataType data);

// data插入在pos之前

void SListInsert(PNode* ppHead, PNode pos, DataType data);

// 删除链表中pos位置的结点

void SListErase(PNode* ppHead, PNode pos);

// 获取链表中结点的个数

size_t Size(PNode pHead);

// 判断链表是否为空,若为空,返回true,否则返回false

size_t Empty(PNode pHead);

// 销毁单链表

void SListDestroy(PNode* ppHead);

// 创建结点,并初始化

PNode BuySListNode(DataType data);

// 打印单链表

void SListPrint(PNode pHead);

#endif  _LINKLIST_H__

 

猜你喜欢

转载自blog.csdn.net/ning_zhi_t/article/details/79243519