单向不带环不带头结点的链表
实现功能:
1、初始化
2、销毁
3、尾插
4、尾删
5、头插
6、头删
7、在pos之后插入新结点
8、在pos之前插入新结点
9、删除指定位置的结点
10、查找结点的位置
代码实现:
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** phead,LinkNodeType value);//尾插
void LinkListPopBack(LinkNode** phead);//尾删
void LinkListPushFront(LinkNode** phead,LinkNodeType value);//头插
void LinkListPopFront(LinkNode** phead);//头删
void LinkListInsert(LinkNode* pos,LinkNodeType value);//在pos之后插入新结点
void LinkListInsertBefore(LinkNode** phead,LinkNode* pos,LinkNodeType value);//在pos之前插入新结点(方法1)
void LinkListInsertBefore2(LinkNode* pos,LinkNodeType value);//在pos之前插入新结点(方法2)
void LinkListErase(LinkNode** phead,LinkNode* pos);//删除指定位置的结点(方法1)
void LinkListErase2(LinkNode** phead,LinkNode* pos);//删除置顶位置的结点(方法2)
LinkNode* LinkListFind(LinkNode* head,LinkNodeType to_find);//查找结点的位置
linklist.c
#include <stdio.h>
#include"linklist.h"
#include<stdlib.h>
LinkNode* CreatNode(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(PLinkNode* phead){
(void)phead;
}
void LinkListPushBack(LinkNode** phead,LinkNodeType value){
if(phead == NULL){
//非法输入
return;
}
if(*phead == NULL){
//空链表
*phead = CreatNode(value);
return;
}
//链表非空
LinkNode* cur = *phead;
while(cur->next != NULL){
cur = cur->next;
}
LinkNode* new_node = CreatNode(value);
cur->next = new_node;
//new_node->next = NULL;
return;
}
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){
pre = cur;
cur = cur->next;
}
//当循环结束,cur就指向了最后一个节点
//pre就指向了倒数第二个节点
pre->next = NULL;
DestroyNode(cur);
return;
}
void LinkListPushFront(LinkNode** phead,LinkNodeType value){
if(phead == NULL){
//非法输入
return;
}
LinkNode* new_node = CreatNode(value);
new_node->next = *phead;
*phead = new_node;
return;
}
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){
if(pos ==NULL){
//非法输入,pos表示一个节点的指针,如果pos为空,说明根本不存在这样的节点
return;
}
LinkNode* new_node = CreatNode(value);
new_node->next = pos->next;
pos->next = new_node;
return;
}
void LinkListInsertBefore(LinkNode** phead,LinkNode* pos,LinkNodeType value){
if(phead == NULL || pos == NULL){
//非法输入
return;
}
if(*phead == pos){
//要插入的位置刚好是头节点
LinkListPushFront(phead,value);
return;
}
LinkNode* cur = *phead;
for(;cur != NULL;cur = cur = cur->next){
if(cur->next ==pos){
break;
}
}
//循环结束之后,需要知道是由于哪种情况下导致的循环结束,到底是找到了pos,还是没找到。
if(cur == NULL){
return;
}
LinkListInsert(cur,value);
return;
}
void LinkListInsertBefore2(LinkNode* pos,LinkNodeType value){
if(pos == NULL){
//非法输入
return;
}
LinkNode* new_node = CreatNode(pos->data);
new_node->next = pos->next;
pos->next = new_node;
pos->data =value;
}
void LinkListErase(LinkNode** phead,LinkNode* pos){
if(phead == NULL || pos ==NULL){
//非法输入
return;
}
if(*phead == NULL){
//空链表
return;
}
LinkNode* cur = *phead;
for(;cur != NULL;cur = cur->next){
if(cur->next == pos){
break;
}
}
//循环结束之后,要去判定,到底是找到了退出的。还是没找到pos退出的。
if(cur == NULL){
return;
}
cur->next = pos->next;
DestroyNode(pos);
return;
}
void LinkListErase2(LinkNode** phead,LinkNode* pos){
if(phead == NULL || pos == NULL){
//非法输入
return;
}
if(*phead == NULL){
return;
}
if(pos->next == NULL){
//要删除的元素刚好是最后一个元素,只能使用原来的尾删的方式来删除了,这时候仍然得遍历链表
LinkListPopBack(phead);
return;
}
pos->data = pos->next->data;
LinkNode* to_erase = pos->next;
pos->next = to_erase->next;
DestroyNode(to_erase);
return;
}
LinkNode* LinkListFind(LinkNode* head,LinkNodeType to_find){
if(head == NULL){
//空链表
return NULL;
}
LinkNode* cur = head;
while(cur){
if(cur->data == to_find){
return cur;
}
cur = cur->next;
}
return NULL;
}
//
//以下为测试代码/
/
#if 1
#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,"尝试对空链表头删");
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&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,"在b之后插入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,"向头节点之前插入节点");
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;
LinkListInsertBefore2(pos1,'x');
LinkListPrintChar(head,"向头节点之前插入节点");
LinkNode* pos2 = head->next->next;
LinkListInsertBefore2(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->next;
LinkListErase(&head,pos);
LinkListPrintChar(head,"删除元素b");
LinkNode* pos2 = (LinkNode*)0x11;
LinkListErase(&head,pos2);
LinkListPrintChar(head,"尝试对一个不存在的位置删除");
}
void TestErase2(){
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListErase2(&head,(LinkNode*)0x11);
LinkListPrintChar(head,"尝试对空链表删除");
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
LinkNode* pos = head->next;
LinkListErase2(&head,pos);
LinkListPrintChar(head,"删除元素b");
}
void TestFind(){
TEST_HEADER;
LinkNode* head;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
LinkNode* pos_x = LinkListFind(head,'x');
printf("pos_x expected NULL,actual %p\n",pos_x);
LinkNode* pos_b = LinkListFind(head,'b');
printf("pos_b expected %p,actual %p\n",head->next,pos_b);
}
int main(){
TestInit();
TestPushBack();
TestPopBack();
TestPushFront();
TestPopFront();
TestInsert();
TestInsertBefore();
TestInsertBefore2();
TestErase();
TestErase2();
TestFind();
return 0;
}
#endif
运行结果: