您的位置:首页 > 其它

链表的基本操作

2018-03-29 10:28 225 查看
对单向的不带环不带头节点的链表做以下操作:

linklist.h

//单向的不带环不带头节点的链表
#pragma once

typedef char LinkNodeType;

typedef struct LinkNode
{
LinkNodeType data;
struct LinkNode *next;
}LinkNode;

typedef LinkNode* PLinkNode;

void LinkListInit(PLinkNode*);                                //初始化

void LinkListDestroy(PLinkNode*);                             //销毁

void LinkListPushBack(LinkNode** head,LinkNodeType value);    //尾插

void LinkListPopBack(LinkNode** head);                        //尾删

void LinkListPushFront(LinkNode** head,LinkNodeType value);   //头插

void LinkListPopFront(LinkNode** head);                       //头删

//将一个元素插入到pos之后
void LinkListInsert(LinkNode* pos,LinkNodeType value);

//将一个元素插入到pos之前
void LinkListInsertBefore(LinkNode** head,LinkNode* pos,LinkNodeType value);

//优化后将元素插入到pos之前
void LinkListInsertBefore2(LinkNode* pos,LinkNodeType value);

//删除元素
void LinkListErase(LinkNode** head,LinkNode* pos);

//优化后的删除
void LinkListErase2(LinkNode** head,LinkNode* pos);

//给一个元素找位置
LinkNode* LinkListFind(LinkNode* head,LinkNodeType to_find);

//判断链表是否为空,链表为空返回1,否则,返回0
int LinkListEmpty(LinkNode* head);

//求链表元素的个数
int LinkListSize(LinkNode* head);

//删除指定值的元素
void LinkListRemove(LinkNode** head,LinkNodeType value);

//删除指定值的所有元素
void LinkListRemoveAll(LinkNode** head,LinkNodeType value);


linklist.c
#include"linklist.h"
#include<stdio.h>
#include<stdlib.h>

LinkNode* CreateNode(LinkNodeType value)//创建节点
{
LinkNode* new_node =(LinkNode *)malloc(sizeof(LinkNode));
new_node->data = value;
new_node->next = NULL;
return new_node;
}

void DestroyNode(LinkNode* node)//销毁节点
{
free(node);
}
void LinkListInit(PLinkNode* node)//链表初始化
{
*node = NULL;
}

void LinkListDestroy(LinkNode** phead)//销毁链表
{
if(phead == NULL)
return;          //非法输入

if(*phead == NULL)
return;          //空链表

LinkNode* cur =  *phead;
while(cur != NULL)
{
LinkNode* to_delete = cur;
cur = cur->next;
DestroyNode(to_delete);
}
*phead = NULL;
}

void LinkListPushBack(LinkNode** phead,LinkNodeType value)//尾插
{
if(phead == NULL)
return;         //非法输入

if(*phead == NULL)
{
//空链表
*phead = CreateNode(value);
return;
}
//链表非空
LinkNode* cur = *phead;
while(cur->next != NULL)
{
cur = cur->next;
}
LinkNode* new_node = CreateNode(value);
cur->next = new_node;
}

void LinkListPopBack(LinkNode** phead)//尾删
{
if(phead ==NULL)
return;        //非法输入

if(*phead == NULL)
return;        //单链表

if((*phead)->next == NULL)
{
//链表只有一个元素
DestroyNode(*phead);
*phead = NULL;
return;
}
LinkNode* cur = *phead;
LinkNode* pre = NULL;
while(cur->next != NULL)
{

4000
pre = cur;
cur = cur->next;
}
pre->next = NULL;
DestroyNode(cur);
return;
}

void LinkListPushFront(LinkNode** phead,LinkNodeType value)//头插
{
if(phead == NULL)
return;                      //非法输入

LinkNode* new_node = CreateNode(value);
new_node->next = *phead;
*phead = new_node;
}

void LinkListPopFront(LinkNode** phead)//头删
{
if(phead == NULL)
return;              //非法输入
if(*phead == NULL)
return;              //空链表

LinkNode* to_erase = *phead;
*phead = (*phead)->next;
DestroyNode(to_erase);
return;
}

void LinkListInsert(LinkNode* pos,LinkNodeType value)//在pos后面插入一个新节点
{
if(pos == NULL)
return;
//非法输入,pos表示一个节点的指针
//如果pos为空,说明根本不存再这样的节点
LinkNode* new_node = CreateNode(value);
new_node->next = pos->next;
pos->next = new_node;
return;
}

void LinkListInsertBefore(LinkNode** phead,LinkNode* pos,LinkNodeType value)//在pos前面插入一个新节点
{
if(phead == NULL ||pos == NULL)
return;                 //非法输入

if(pos == *phead)
{
//要插的地方刚好是头节点
LinkListPushFront(phead,value);
return;
}
LinkNode* cur = *phead;
for( ;cur != NULL;cur = cur->next)
{
if(cur->next == pos)
{
break;          //跳出循环时cur刚好是pos的前一个节点
}
}
if(cur == NULL)
{
return;
}
LinkListInsert(cur,value);
}

//我们可以看到在pos前面插入新节点时,需要遍历链表,找到它的前一个节点,这种算法时间复杂度为O(n);
//而下面这种算法,通过交换pos位置和新插入节点的数据的方法可以达到同样的目的,时间复杂度为O(1).

void LinkListInsertBefore2(LinkNode* pos,LinkNodeType value)
{
if(pos == NULL)
{
return;            //非法输入
}
LinkListInsert(pos,pos->data);
pos->data = value;
//交换新插入的节点和pos的位置
}

void LinkListErase(LinkNode** phead,LinkNode* pos)//删除
{
if((phead == NULL)||(pos == NULL))
return;       //非法输入

if(*phead == NULL)
return;      //空链表

if(*phead == pos)
LinkListPopFront(phead);//如果pos是起始位置,调用头删

LinkNode* cur = *phead;
for( ;cur != NULL;cur = cur->next)
{
if(cur->next == pos)
{
cur->next = pos->next;
pos->next = NULL;
DestroyNode(pos);
}
}
return;
}

//删除pos位置时,需要遍历链表,找到它的前一个节点,这种算法时间复杂度为O(n);
//而下面这种算法,将pos->next的数据赋给pos然后删除pos->next节点的方法可以达到同样的目的,时间复杂度为O(1).

void LinkListErase2(LinkNode** phead,LinkNode* pos)
{

if((phead == NULL)||(pos == NULL))
return;       //非法输入

if(*phead == NULL)
return;      //空链表

pos->data = pos->next->data;
LinkNode* to_erase = pos->next;
pos->next = to_erase->next;
DestroyNode(to_erase);
return;
}

LinkNode* LinkListFind(LinkNode* phead,LinkNodeType to_find)//找指定元素的位置
{
if(phead == NULL)
return NULL;            //空链表

LinkNode* cur = phead;
while(cur != NULL)
{
if(cur->data == to_find)
{
return cur;
}
cur = cur->next;
}
return NULL;
}

int  LinkListEmpty(LinkNode* phead)//判断链表是否为空
{
if(phead == NULL)
{
return 1;           //空链表
}
else
{
return 0;
}
}

int LinkListSize(LinkNode* phead)//求链表大小
{
if(phead == NULL)
return;             //空链表

LinkNode* cur = phead;
size_t count = 0;
for( ;cur != NULL;cur = cur->next)
{
count++;
}
return count;
}

void LinkListRemove(LinkNode** phead,LinkNodeType value)//移除指定值的元素
{
if(phead == NULL)
return;            //非法输入

if(*phead == NULL)
return;            //空链表

LinkNode* cur = LinkListFind(*phead,value);
if(cur == NULL)
{
return;      //没找到
}
LinkListErase(phead,cur);
}

void LinkListRemoveAll(LinkNode** phead,LinkNodeType value)//移除指定值的所有元素
{

if(phead == NULL)
return;            //非法输入

if(*phead == NULL)
return;            //空链表

while(1)
{
LinkNode* cur = LinkListFind(*phead,value);
if(cur == NULL)
{
return;
}
LinkListErase(phead,cur);
}
}
///////////////////////////
//以下是测试代码
///////////////////////////

#include<stdio.h>
#define TEST_HEADER printf("\n=====================%s====================\n",__FUNCTION__)

void LinkListPrintChar(LinkNode* head,const char* msg)
{
printf("[%s]\n",msg);
LinkNode* cur = head;
for( ;cur != NULL;cur = cur->next)
{
printf("[%c|%p] ",cur->data,cur);
}
printf("\n");

}

void TestInit()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);

}

void TestPushBack()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
LinkListPrintChar(head,"尾插四个元素");
}

void TestPopBack()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPopBack(&head);
LinkListPrintChar(head," 对空链表尾删");

LinkListPushBack(&head,'a');
LinkListPopBack(&head);
LinkListPrintChar(head,"对只有一个元素的链表尾删");

LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
LinkListPopBack(&head);
LinkListPopBack(&head);
LinkListPrintChar(head,"尾删两个元素");
LinkListPopBack(&head);
LinkListPopBack(&head);
LinkListPrintChar(head,"再尾删两个元素");
}

void TestPushFront()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushFront(&head,'a');
LinkListPushFront(&head,'b');
LinkListPushFront(&head,'c');
LinkListPushFront(&head,'d');
LinkListPrintChar(head,"头插四个元素");
}

void TestPopFront()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPopFront(&head);
LinkListPrintChar(head,"对空链表头删");

LinkListPushFront(&head,'a');
LinkListPushFront(&head,'b');
LinkListPushFront(&head,'c');
LinkListPushFront(&head,'d');
LinkListPrintChar(head,"头插四个元素");

LinkListPopFront(&head);
LinkListPopFront(&head);
LinkListPrintChar(head,"头删两个元素");
LinkListPopFront(&head);
LinkListPopFront(&head);
LinkListPrintChar(head,"再头删两个元素");
}

void TestInsert()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

LinkNode* pos = head->next;
LinkListInsert(pos,'x');
LinkListPrintChar(head,"插入'x'元素");
}

void TestInsertBefore()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

LinkNode* pos1 = head;
LinkListInsertBefore(&head,pos1,'x');
LinkListPrintChar(head,"向头节点之前插入'x'元素");

LinkNode* pos2 = head->next->next;
LinkListInsertBefore(&head,pos2,'y');
LinkListPrintChar(head,"向'b'之前插入'y'元素");
}

void TestInsertBefore2()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

LinkNode* pos1 = head;
LinkListInsertBefore(&head,pos1,'x');
LinkListPrintChar(head,"向头节点之前插入'x'元素");

LinkNode* pos2 = head->next->next;
LinkListInsertBefore(&head,pos2,'y');
LinkListPrintChar(head,"向'b'之前插入'y'元素");
}

void TestErase()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);

LinkListErase(&head,(LinkNode*)0x11);
LinkListPrintChar(head,"尝试对空链表删除");

LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

LinkNode* pos= head;
LinkListErase(&head,pos);
LinkListPrintChar(head,"删除元素'a'");

LinkNode* pos2 = (LinkNode*)0x10;
LinkListErase(&head,pos2);
LinkListPrintChar(head,"尝试对一个不存在的位置删除");
}

void TestErase2()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);

LinkListErase(&head,(LinkNode*)0x11);
LinkListPrintChar(head,"尝试对空链表删除");

LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

LinkNode* pos = head->next;
LinkListErase(&head,pos);
LinkListPrintChar(head,"删除元素'b'");

LinkNode* pos2 = (LinkNode*)0x10;
LinkListErase(&head,pos2);
LinkListPrintChar(head,"尝试对一个不存在的位置删除");
}

void TestFind()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);

LinkNode* pos =  LinkListFind(head,'a');
printf("'a'的地址是:%p\n",pos);

LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

LinkNode* pos1 =  LinkListFind(head,'c');
printf("'c'的地址是:%p\n",pos1);

LinkNode* pos2 =  LinkListFind(head,'x');
printf("'x'的地址是:%p",pos2);
}

void TestEmpty()
{

TEST_HEADER;
LinkNode* head;
LinkListInit(&head);

size_t cur1 = LinkListEmpty(head);
printf("%d\n",cur1);

LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

size_t cur2 = LinkListEmpty(head);
printf("%d",cur2);
}

void TestSize()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);

size_t cur1 = LinkListSize(head);
printf("%d\n",cur1);

LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

size_t cur2 = LinkListSize(head);
printf("%d",cur2);
}

void TestRemove()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);

LinkListRemove(&head,'a');
LinkListPrintChar(head,"尝试对空链表删除");

LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');

LinkListRemove(&head,'a');
LinkListPrintChar(head,"删除元素'a'");

LinkListRemove(&head,'x');
LinkListPrintChar(head,"尝试删除一个不存在的值");
}
void TestRemoveAll()
{
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);

LinkListRemoveAll(&head,'a');
LinkListPrintChar(head,"尝试对空链表删除");

LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'d');
LinkListPushBack(&head,'a');

LinkListRemoveAll(&head,'a');
LinkListPrintChar(head,"删除元素'a'");

LinkListRemoveAll(&head,'x');
LinkListPrintChar(head,"尝试删除一个不存在的值");
}
int main()
{
TestInit();
TestPushBack();
TestPopBack();
TestPushFront();
TestPopFront();
TestInsert();
TestInsertBefore();
TestInsertBefore2();
TestErase();
TestErase2();
TestFind();
TestEmpty();
TestSize();
TestRemove();
TestRemoveAll();
printf("\n");
return 0;
}


注意:对链表操作时要看传入的是一级指针还是二级指针,修改头指针的指向用二级指针,其他用一级指针。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: