数据结构与算法基础之线性表链式实现
学习来源:
数据结构与算法基础(青岛大学-王卓)
地址:
https://www.bilibili.com/video/BV1nJ411V7bd?p=22&spm_id_from=pageDriver
背景:
实现视频里老师的伪代码,并不完全一样,但基本雷同。
更新
2021/5/25
增加linklist函数,用于何必两个顺序表
2021/6/19
修改所有代码,可以兼容所有数据类型。
代码:
ChainDynamic.h
#ifndef _CHAINDYNAMIC_H_
#define _CHAINDYNAMIC_H_
typedef struct ChainDynamic *ChainDynamic;//Chain list object
typedef void (*ChainOwnShow)(void *);
//Create the chain list
//The "DataSize" is the data type size of each chain element.
ChainDynamic Create_ChainDynamic(unsigned DataSize);
//Add a element with "Data" to the chain list "cd" on list tail.
void AddTail_ChainDynamic(ChainDynamic cd, void *Data);
//Get the "index" data from chain list "cd" and store it into "Data".
void Get_ChainDynamic(ChainDynamic cd, unsigned index, void *Data);
//Show chain list "cd" element's data on console.
//The "show" is your function about how to show your list's data.
void Show_ChainDynamic(ChainDynamic cd, ChainOwnShow show);
//Add an element with "Data" to the chain list "cd" on list head.
void AddHead_ChainDynamic(ChainDynamic cd, void *Data);
//Delete an element of chain list "cd" on list head.
void DeleteHead_ChainDynamic(ChainDynamic cd);
//Delete an element of chain list "cd" on list tail.
void DeleteTail_ChainDynamic(ChainDynamic cd);
//Empty the chain list "cd".
void Clear_ChainDynamic(ChainDynamic cd);
//Destroy chain list "cd".
void Destroy_ChainDynamic(ChainDynamic *pcd);
//Insert a node which data is "Data" into chain list "cd" before "index" node.
void Insert_ChainDynamic(ChainDynamic cd, unsigned index, void *Data);
//Remove the "index" node of chain list "cd".
void Remove_ChainDynamic(ChainDynamic cd, unsigned index);
//Change the value of node in the chain.
void Change_ChainDynamic(ChainDynamic cd, unsigned index, void *Data);
//Judge if chain list "cd" is empty.
int IsEmpty_ChainDynamic(ChainDynamic cd);
#endif
ChainDynamic.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ChainDynamic.h"
#include "CommonFunc.h"
struct Node
{
void *Data;//Data pointer
struct Node *NextNode;//Next node address
};
typedef struct Node Node;
struct ChainDynamic
{
Node *head;//List head node.
unsigned DataSize;//List each data's type size.
};
static Node * GetNode_ChainDynamic(ChainDynamic cd, unsigned index);
static unsigned GetLength_ChainDynamic(ChainDynamic cd);
void Destroy_ChainDynamic(ChainDynamic *pcd)
{
NULLPointOut(pcd, "Destroy_ChainDynamic", "pcd");
NULLPointOut(*pcd, "Destroy_ChainDynamic", "cd");
NULLPointOut((*pcd)->head, "Destroy_ChainDynamic", "head");
Clear_ChainDynamic(*pcd);
free((*pcd)->head);
free(*pcd);
*pcd = NULL;
return;
}
void Clear_ChainDynamic(ChainDynamic cd)
{
NULLPointOut(cd, "Clear_ChainDynamic", "cd");
while(!IsEmpty_ChainDynamic(cd))
{
DeleteHead_ChainDynamic(cd);
}
return;
}
void DeleteHead_ChainDynamic(ChainDynamic cd)
{
NULLPointOut(cd, "DeleteHead_ChainDynamic", "cd");
Remove_ChainDynamic(cd, 1);
return;
}
void DeleteTail_ChainDynamic(ChainDynamic cd)
{
NULLPointOut(cd, "DeleteTail_ChainDynamic", "cd");
Remove_ChainDynamic(cd, GetLength_ChainDynamic(cd));
return;
}
void AddHead_ChainDynamic(ChainDynamic cd, void *Data)
{
NULLPointOut(cd, "AddHead_ChainDynamic", "cd");
NULLPointOut(Data, "AddHead_ChainDynamic", "Data");
Insert_ChainDynamic(cd, 1, Data);
return;
}
void AddTail_ChainDynamic(ChainDynamic cd, void *Data)
{
NULLPointOut(cd, "AddTail_ChainDynamic", "cd");
NULLPointOut(Data, "AddTail_ChainDynamic", "Data");
Insert_ChainDynamic(cd, GetLength_ChainDynamic(cd) + 1, Data);
return;
}
void Change_ChainDynamic(ChainDynamic cd, unsigned index, void *Data)
{
NULLPointOut(cd, "Change_ChainDynamic", "cd");
NULLPointOut(Data, "Change_ChainDynamic", "Data");
if(index > GetLength_ChainDynamic(cd) || index == 0)
{
puts("Change_ChainDynamic ERROR: index overstep list's boundary.");
exit(-1);
}
Node *n = GetNode_ChainDynamic(cd, index);
memcpy(n->Data, Data, cd->DataSize);
return;
}
void Remove_ChainDynamic(ChainDynamic cd, unsigned index)
{
NULLPointOut(cd, "Remove_ChainDynamic", "cd");
if(index > GetLength_ChainDynamic(cd) || index == 0)
{
puts("Remove_ChainDynamic ERROR: index overstep list's boundary.");
exit(-1);
}
Node *before = GetNode_ChainDynamic(cd, index - 1);
Node *n = GetNode_ChainDynamic(cd, index);
before->NextNode = n->NextNode;
free(n->Data);
free(n);
return;
}
void Get_ChainDynamic(ChainDynamic cd, unsigned index, void *Data)
{
NULLPointOut(cd, "Get_ChainDynamic", "cd");
NULLPointOut(Data, "Get_ChainDynamic", "Data");
if(index > GetLength_ChainDynamic(cd) || index == 0)
{
puts("Get_ChainDynamic ERROR: index overstep list's boundary.");
exit(-1);
}
Node *n = GetNode_ChainDynamic(cd, index);
memcpy(Data, n->Data, cd->DataSize);
return;
}
void Show_ChainDynamic(ChainDynamic cd, ChainOwnShow show)
{
NULLPointOut(cd, "Show_ChainDynamic", "cd");
puts("-------------");
printf("length=%u, DataSize=%u\n", GetLength_ChainDynamic(cd), cd->DataSize);
Node *n = cd->head;
while(n->NextNode != NULL)
{
n = n->NextNode;
show(n->Data);
}
puts("");
puts("");
return;
}
//Get the "index" node from chain list "cd".
static Node * GetNode_ChainDynamic(ChainDynamic cd, unsigned index)
{
NULLPointOut(cd, "GetNode_ChainDynamic", "cd");
if(index > GetLength_ChainDynamic(cd))
{
puts("GetNode_ChainDynamic ERROR: index overstep list's boundary");
exit(-1);
}
unsigned i;
Node *n = cd->head;
for(i = 0; i < index; i++)
{
n = n->NextNode;
}
return n;
}
int IsEmpty_ChainDynamic(ChainDynamic cd)
{
NULLPointOut(cd, "IsEmpty_ChainDynamic", "cd");
return GetLength_ChainDynamic(cd) == 0 ? 1 : 0;
}
//Get chain list "cd" length now.
static unsigned GetLength_ChainDynamic(ChainDynamic cd)
{
NULLPointOut(cd, "GetLength_ChainDynamic", "cd");
Node *n = cd->head;
unsigned i = 0;
while(n->NextNode != NULL)
{
i++;
n = n->NextNode;
}
return i;
}
ChainDynamic Create_ChainDynamic(unsigned DataSize)
{
if(DataSize == 0)
{
return NULL;
}
ChainDynamic cd = (ChainDynamic)malloc(sizeof(struct ChainDynamic));
NULLMallocOut(cd, "Create_ChainDynamic", "cd");
Node *head = (Node *)malloc(sizeof(Node));
NULLMallocOut(head, "Create_ChainDynamic", "head");
head->Data = NULL;
head->NextNode = NULL;
cd->head = head;
cd->DataSize = DataSize;
return cd;
}
void Insert_ChainDynamic(ChainDynamic cd, unsigned index, void *Data)
{
NULLPointOut(cd, "Insert_ChainDynamic", "cd");
NULLPointOut(Data, "Insert_ChainDynamic", "Data");
if(index > GetLength_ChainDynamic(cd) + 1 || index == 0)
{
puts("Insert_ChainDynamic ERROR: index overstep list's boundary.");
exit(-1);
}
void *newData = malloc(cd->DataSize);
NULLMallocOut(newData, "Insert_ChainDynamic", "Data");
Node *n = (Node *)malloc(sizeof(Node));
NULLMallocOut(n, "Insert_ChainDynamic", "n");
memcpy(newData, Data, cd->DataSize);
n->Data = newData;
Node *before = GetNode_ChainDynamic(cd, index - 1);
n->NextNode = before->NextNode;
before->NextNode = n;
return;
}
CommonFunc.h
#ifndef _COMMONFUNC_H_
#define _COMMONFUNC_H_
//If p equal null, exit program and pop a err message.
//The parameter 'func' is error function name.
//The paremeter 'element' is problem variables.
void NULLPointOut(void *p, char *func, char *element);
void NULLMallocOut(void *p, char *func, char *element);
#endif
CommonFunc.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void NULLPointOut(void *p, char *func, char *element)
{
if(func == NULL)
{
puts("NULLPointOut ERROR: NULL point exception 'func'");
exit(-1);
}
else if(element == NULL)
{
puts("NULLPointOut ERROR: NULL point exception 'element'");
exit(-1);
}
if(p == NULL)
{
printf("%s ERROR: NULL point exception '%s'\n", func, element);
exit(-1);
}
return;
}
void NULLMallocOut(void *p, char *func, char *element)
{
NULLPointOut(func, "NULLMallocOut", "func");
NULLPointOut(element, "NULLMallocOut", "element");
if(p == NULL)
{
printf("%s ERROR: Malloc error '%s'\n", func, element);
exit(-1);
}
return;
}
example.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CommonFunc.h"
#include "ChainDynamic.h"
void myshow(void *Data)
{
char *a = (char *)Data;
printf("%s ", a);
return;
}
int main(void)
{
ChainDynamic cd = Create_ChainDynamic(5);
AddHead_ChainDynamic(cd, "abcd");
AddHead_ChainDynamic(cd, "qwer");
AddHead_ChainDynamic(cd, "1234");
Show_ChainDynamic(cd, myshow);
Clear_ChainDynamic(cd);
Show_ChainDynamic(cd, myshow);
AddHead_ChainDynamic(cd, "abcd");
AddHead_ChainDynamic(cd, "qwer");
AddHead_ChainDynamic(cd, "1234");
Show_ChainDynamic(cd, myshow);
Destroy_ChainDynamic(&cd);
return 0;
}