C++單向鏈表之創建、插入、刪除、查找、交換鏈表節點

鏈表:
   鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。 相比於線性表順序結構,鏈表比較方便插入和刪除操作。
   下面直接通過代碼進行展示:包括初始化一個可以指向任何數據類型的鏈表、鏈表中指定位置插入節點元素、鏈表中刪除指定位置的節點元素、獲取鏈表的長度、在鏈表中查找指定的元素並返回當前元素所在的索引值、返回鏈表第一個節點、釋放鏈表內存、打印鏈表、交換鏈表節點(鏈表從前向後第K個節點與從後向前第K個節點進行交換)。
LinkList.h

#pragma once
#include <windows.h>
#include <stdio.h>

// 鏈表結點
typedef struct LINKNODE
{
	void* data;  // 可以指向任何類型的數據
	LINKNODE* next;
}LinkNode;

// 鏈表結構體
typedef struct LINKLIST
{
	int size;
	LinkNode* head;
}LinkList;

// 打印函數指針
typedef void(*PRINTLINKNODE)(void*);

// 初始化鏈表
LinkList* Init_LinkList();

// 指定位置插入
void Insert_LinkList(LinkList* list, int pos, void* data);

// 交換順序與逆序對應的第Key個值
void Key_LinkList(LinkList* list, int key);

// 指定位置刪除
void RemoveByPos_LinkList(LinkList* list, int pos);

// 獲得鏈表的長度
int GetLinkListSize(LinkList* list);

// 查找(根據數據返回索引)
int Find_LinkList(LinkList* list, void* data);

// 返回第一個結點
void* Front_LinkList(LinkList* list);

// 釋放鏈表內存
void FreeMem_LinkList(LinkList* list);

// 打印鏈表
void Print_LinkList(LinkList* list, PRINTLINKNODE);

LinkList.cpp

#include "LinkList.h"

// 初始化鏈表
LinkList* Init_LinkList()
{
	LinkList* list = (LinkList*)malloc(sizeof(LinkList));
	list->size = 0;
	// 頭結點是不保存數據的
	list->head = (LinkNode*)malloc(sizeof(LinkNode));
	list->head->data = NULL;
	list->head->next = NULL;
	return list;
}

// 指定位置插入
void Insert_LinkList(LinkList* list, int pos, void* data)
{
	if (list == NULL || data == NULL)
	{
		return;
	}
	if (pos < 0 || pos > list->size)
	{
		pos = list->size;
	}
	// 創建新的結點
	LinkNode* InsertNode = (LinkNode*)malloc(sizeof(LinkNode));
	InsertNode->data = data;
	InsertNode->next = NULL;
	// 找結點
	LinkNode* pCurrent = list->head;
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	// 將新結點插入鏈表
	InsertNode->next = pCurrent->next;
	pCurrent->next = InsertNode;
	// 鏈表大小加1
	list->size++;
}

// 指定位置刪除
void RemoveByPos_LinkList(LinkList* list, int pos)
{
	if (list == NULL)
	{
		return;
	}
	if (pos < 0 || pos >= list->size)
	{
		return;
	}
	LinkNode* pCurrent = list->head;
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	LinkNode* pDel = pCurrent->next;
	pCurrent->next = pCurrent->next->next;
	free(pDel);
	// 鏈表長度減一
	list->size--;
}

// 獲得鏈表的長度
int GetLinkListSize(LinkList* list)
{
	if (list == NULL)
	{
		return -1;
	}
	return list->size;
}

// 查找(根據數據返回索引)
int Find_LinkList(LinkList* list, void* data)
{
	if (list == NULL || data == NULL)
	{
		return -1;
	}
	int pos = -1;
	LinkNode* pCurrent = list->head->next;
	for (int i = 0; i < list->size; i++)
	{
		if (pCurrent->data == data)
		{
			pos = i;
			break;
		}
		pCurrent = pCurrent->next;
	}
	return pos;
}

// 返回第一個結點
void* Front_LinkList(LinkList* list)
{
	return list->head->next->data;
}

// 釋放鏈表內存
void FreeMem_LinkList(LinkList* list)
{
	if (list == NULL)
	{
		return;
	}
	LinkNode* pCurrent = list->head;
	while (pCurrent != NULL)
	{
		LinkNode* pDel = pCurrent;
		pCurrent = pCurrent->next;
		free(pDel);
	}
	list->size = 0;
	free(list);
}

// 打印鏈表
void Print_LinkList(LinkList* list, PRINTLINKNODE print)
{
	if (list == NULL)
	{
		return;
	}
	LinkNode* pCurrent = list->head->next;
	while (pCurrent != NULL)
	{
		print(pCurrent->data);
		pCurrent = pCurrent->next;
	}
}

// 交換 順序與逆序對應的第Key個值
void Key_LinkList(LinkList* list, int key)
{
	int total_len;
	int change;

	//獲取鏈表長度
	total_len = GetLinkListSize(list);

	if (key / 2 == 1)
	{
		printf("交換後與交換前,鏈表數據無變化 !!\n");
		return;
	}

	if (key < (total_len - key))
	{
		change = key;
	}
	else
	{
		change = total_len - key - 1;
	}

	LinkNode* pCurrent = list->head;

	for (int i = 0; i < total_len; i++)
	{
		pCurrent = pCurrent->next;
		if (i == change)
		{
			Insert_LinkList(list, total_len - change, pCurrent->data);
		}
		else if (i == total_len - change - 1)
		{
			Insert_LinkList(list, change, pCurrent->data);
		}
	}
	RemoveByPos_LinkList(list, change + 1);
	RemoveByPos_LinkList(list, total_len - change - 1);
}

main.cpp

// list.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
#include <iostream>
#include "LinkList.h"

//自定義數據類型
typedef struct PERSON
{
	char name[64];
	int age;
	int score;
}Person;

//打印函數
void MyPrint(void* data)
{
	Person* p = (Person*)data;
	printf("Name:%s Age:%d Score:%d\n", p->name, p->age, p->score);
}

int main()
{
	//創建鏈表
	LinkList* list = Init_LinkList();

	//創建數據
	Person p1 = { "aaa", 6, 6 };
	Person p2 = { "bbb", 5, 5 };
	Person p3 = { "ccc", 4, 4 };
	Person p4 = { "ddd", 3, 3 };
	Person p5 = { "eee", 2, 2 };
	Person p6 = { "fff", 1, 1 };
	Person p7 = { "ggg", 0, 0 };

	//數據插入鏈表
	Insert_LinkList(list, 0, &p1);
	Insert_LinkList(list, 0, &p2);
	Insert_LinkList(list, 0, &p3);
	Insert_LinkList(list, 0, &p4);
	Insert_LinkList(list, 0, &p5);
	Insert_LinkList(list, 0, &p6);
	Insert_LinkList(list, 0, &p7);

	//打印
	printf("打印原始鏈表數據:\n");
	Print_LinkList(list, MyPrint);
	printf("\n");
	printf("\n");

	//交換,Key必須大於0
	printf("給定一個數字Key,把從前向後第Key個節點與從後向前第Key個節點進行交換:\n");
	int Key = 2;

	if (Key < 1 || Key > (GetLinkListSize(list) -1 ))
	{
		printf("error: key invaid !!");
		return 0;
	}

	printf("Key = %d\n",Key);
	//交換
	Key_LinkList(list, Key -1);
	//打印
	Print_LinkList(list, MyPrint);
	printf("\n");
	printf("\n");

	//刪除3
	printf("測試刪除某一個節點:\n");
	RemoveByPos_LinkList(list, 3);
	//打印
	Print_LinkList(list, MyPrint);
	printf("\n");
	printf("\n");

	//返回第一個結點
	printf("-----查找鏈表首個節點------------\n");
	Person* ret = (Person*)Front_LinkList(list);
	printf("Name:%s Age:%d Score:%d\n", ret->name, ret->age, ret->score);

	//銷燬鏈表
	Front_LinkList(list);
	getchar();
	return 0;
}

如下效果圖:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章