- 插入:头插入,尾插入,及指定位置插入
- 删除:头删除,尾删除,及指定位置插入
- 逆序:
- 查找:
- 计数:
- 打印:
#include <stdio.h>
#include <Windows.h>
//节点结构体
#define MAX_LEN_IN_KEY 16
typedef struct Node {
char key[MAX_LEN_IN_KEY+1];
int value;
struct Node* next;
};
typedef Node* PNode;
void domemcpy(char *dest, char *src){
int count = (MAX_LEN_IN_KEY < strlen(src)) ? MAX_LEN_IN_KEY : strlen(src);
memset((void*)dest,0,count+1);
strncpy(dest,src,count);
}
//1.构建一个结点
PNode buildNode(char* key,int value){
printf("%s\n",__func__);
PNode node = (PNode)malloc(sizeof(Node));
if (node == NULL){
return NULL;
}
domemcpy(node->key,key);
node->value = value;
node->next = NULL;
return node;
}
//2.初始化头结点
PNode initLinklist(char* key, int value) {
return buildNode(key,value);
}
//3.尾插
PNode insertNodeIntoBack(PNode *pHead, char* key, int value){
printf("%s\n", __func__);
PNode newNode = buildNode(key,value);
if (newNode == NULL) {
return NULL;
}
//(1)链表为空时,直接让phead指向新节点即可
if (NULL == (*pHead)){
printf("linklist is empty,set it as head\n");
*pHead = newNode;
return newNode;
}
//(2)链表不空时,遍历一遍链表,找到最后一个节点,连接在最后一个节点的的后面
PNode pCur = *pHead;
while (pCur->next != NULL){
pCur = pCur->next;
}
pCur->next = newNode;
return newNode;
}
//4.尾删
void deleteNodeFromBack(PNode *pHead)
{
printf("%s\n", __func__);
if (NULL == (*pHead)){ //(1)链表为空时,直接返回
printf("linklist is empty,no need to delete\n");
return;
}else if (NULL == (*pHead)->next) { //(2)链表中只有一个结点时,free这个节点,并将phead置空
printf("linklist has only one node\n");
free(*pHead);
*pHead = NULL;
}else{
printf("linklist has more than one node\n");
PNode pCur = *pHead;//指向当前节点
PNode pPrev = pCur; //指向前一个节点
//(3)链表中有多个节点时,遍历一遍链表,找到最后一个节点(pCur->next == NULL),并且保存最后一个节点的前一个节点的信息
while (pCur->next != NULL){
pPrev = pCur;
pCur = pCur->next;
}
free(pCur);
pPrev->next = NULL;
}
}
//5.头插
PNode insertNodeIntoFront(PNode *pHead, char* key, int value){
printf("%s\n", __func__);
PNode newNode = buildNode(key,value);
if (newNode == NULL) {
return NULL;
}
//(1) 链表为空时:直接让头结点指向新的节点即可
if (NULL == (*pHead)){
printf("linklist is empty,set it as head\n");
*pHead = newNode;
}else{
//(2)当链表有一个节点或者多个节点时,连接在头节点的的前面,并修改新节点作为头节点
newNode->next = *pHead;
*pHead = newNode;
}
return newNode;
}
//6.头删
void deleteNodeFromFront(PNode *pHead){
printf("%s\n", __func__);
//链表为空时:直接返回,不需要删除
if (NULL == (*pHead)) {
printf("linklist is empty,no need to delete\n");
return;
}
//链表不为空时:有一个节点和有多个节点可以使用相同的逻辑:旧头节点的下一个节点作为新节点,并将旧头结点置空
PNode pDel = *pHead;
*pHead = (*pHead)->next;
free(pDel);
}
//7.pos位置上插入一个节点
PNode insertNodeAtPos(PNode *pHead,PNode pos, char* key, int value){
printf("%s\n", __func__);
if (*pHead == NULL || pos == NULL) { //(1)链表为空时,直接返回 //(2)pos位置是否为空
return NULL;
}
PNode newNode = NULL;
bool bFind = false;
PNode pCur = *pHead;//指向当前节点
while (pCur != NULL) {
if (pCur == pos) { //(3)Pos节点是否存在
bFind = true;
break;
}
pCur = pCur->next;
}
if (bFind) {
newNode = buildNode(key, value);
if (newNode) {
//插入一个节点(由于是单链表,所以只能插在pos位置的后面)
newNode->next = pos->next;
pos->next = newNode;
}
}
else {
printf("Pos node is not found to insert\n");
}
return newNode;
}
//8.pos位置上删除一个节点
void deleteNodeAtPos(PNode* pHead, PNode pos){
printf("%s\n", __func__);
if (*pHead == NULL || pos == NULL) { //(1)链表为空时,直接返回 ;pos位置是否为空
return;
}
//(2)pos不为空且pos为头结点时,这时就可以转化为删除第一个节点,操作步骤同上面的头删
if ((*pHead) == pos){
*pHead = pos->next; //*pHead = (*pHead)->next;
free(pos);
}else{ //(3)当pos不是第一个节点时
PNode pCur = *pHead;//指向当前节点
PNode pPrev = pCur; //指向前一个节点
bool bFind = false;
while (pCur->next != NULL) {
if (pCur == pos) { //Pos节点是否存在
bFind = true;
break;
}
pPrev = pCur;
pCur = pCur->next;
}
if (bFind) {
pPrev->next = pos->next;
free(pos);
}
else {
printf("Pos node is not found to delet\n");
}
}
}
//9.逆序
PNode reverseListlink(PNode* pHead) {
printf("%s\n", __func__);
if (*pHead == NULL) { //(1)链表为空,直接返回
return *pHead;
}else if ((*pHead)->next == NULL) { //(2)链表只有一个节点,不需要逆序
return *pHead;
}else { //(3)链表多个一个节点
PNode pPre = *pHead;
PNode pCur = pPre->next;
(*pHead)->next = NULL; //(旧)头结点next为NULL
while (pCur != NULL)
{
PNode pTmp = NULL;
pTmp = pCur; //保存(旧)当前节点
pCur = pCur->next; //(新)当前节点后移一节点
pTmp->next = pPre; //(旧)当前节点指向前节点
pPre = pTmp; //前节点后移一节点
}
*pHead = pPre; //(新)头节点
return *pHead;
}
}
//10.查找key对应的节点
PNode findNode(PNode pHead, char* key)
{
printf("%s\n", __func__);
PNode pCur = pHead;
while (pCur)
{
int lenExpect = strlen(key);
int lenMeasured = strlen(pCur->key);
if (lenExpect == lenMeasured && strncmp(pCur->key,key, lenExpect) == 0) //如果存在,返回所在位置
{
return pCur;
}
pCur = pCur->next;
}
printf("can not find the node of key\n");
return NULL; //不存在,返回NULL
}
//11.打印单链表
void printList(PNode pHead){
PNode pCur = pHead;
while (pCur){
printf("key:%s,value:%d\n", pCur->key,pCur->value);
pCur = pCur->next;
}
}
//11.得到单链表中节点的个数
int sizeList(PNode pHead){
size_t count = 0;
PNode pCur = pHead;
while (pCur)
{
pCur = pCur->next;
count++;
}
return count;
}
int main()
{
char key[] = "201901";
int value = 1;
PNode pHead = NULL;
#if 1
pHead = initLinklist(key, value);;
#endif
#if 1
char key2[] = "201902";
int value2 = 2;
insertNodeIntoBack(&pHead, key2, value2);
#endif
#if 1
char key3[] = "201903";
int value3 = 4;
insertNodeIntoFront(&pHead, key3, value3);
#endif
#if 0
deleteNodeFromBack(&pHead);
#endif
#if 0
deleteNodeFromFront(&pHead);
#endif
PNode pPos = NULL;
#if 1
pPos = findNode(pHead, key);
#endif
#if 1
char key4[] = "201904";
int value4 = 8;
insertNodeAtPos(&pHead, pPos, key4, value4);
#endif
#if 0
deleteNodeAtPos(&pHead,pPos);
#endif
#if 1
reverseListlink(&pHead);
#endif
int size = sizeList(pHead);
printf("linklist size:%d\n",size);
printList(pHead);
}