(C++)数据结构——链表:在类中实现双向循环链表

在这里记录一下我实现的双向循环链表,一些接口函数我都实现了一遍。

首先是命名为List.h的头文件

#include"iostream"
#include"string"
#include"cstdlib"
#include"cassert"
#include"cstring"

using namespace std;

//using struction to create the node of the list
#define ElemType int
typedef struct ListNode
{
	ElemType data;
	//if you want ot achieve the two-direction list, you must use two pointers
	struct ListNode* pre;
	struct ListNode* next;
};

//this function is used to compare if two string is the same
//it is mainly used to help calculate the how many elements are equal.
bool CompareStr(string str1, string str2);



class List
{
private:
	ListNode* phead; // create the soilder pointer to defend the list
public:
	List(); // initate the list first
	void ListPushBack(ElemType pushback_value); // insert new node on the tail of the list
	void ListPopBack();
	void ListPushFront(ElemType pushfront_value); // insert new node on the front of the list
	void ListPopFront();  // delete the value at the top of the list
	void ListPrint();
	bool DestoryList();  // this function is used to destory the list
	bool ClearList();
	ListNode* SearchList(ElemType search_value);  // find the value you want to search and return the node pointer
	void InsertList(ElemType insert_value, int location); // deliver the element you want to insert and the location of it
	void DeleteList(int location); // delete the value which you want

	int CalculateList(ElemType value_youfind); // return the number of the goal you want to find
};

List::List()
{
	//remember to allocate the memory to the phead
	//or your code will be error. 
	phead = (ListNode*)malloc(sizeof(ListNode));
	phead->next = phead;
	phead->pre = phead;
}

void List::ListPushBack(ElemType pushback_value)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	assert(newnode);
	newnode->data = pushback_value;
	
	ListNode* tail = phead->pre;  // find the tail of the list
	tail->next = newnode;
	newnode->pre = tail;
	newnode->next = phead;
	phead->pre = newnode;
}

void List::ListPopBack()
{
	//find the tail of the list
	ListNode* tail = phead->pre;
	ListNode* pre_tail = tail->pre;
	pre_tail->next = phead;
	phead->pre = pre_tail;
	free(tail);
}


void List::ListPrint()
{
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		cout << cur->data;
		cur = cur->next;
	}
	cout << endl;
}

bool List::DestoryList()
{
	//ListNode* cur = phead->pre; //desroty the list from the tail of the list
	ListNode* head = phead->next;
	ListNode* tmp = phead;
	while (head->next != head)
	{
		//ListNode* tmp = phead;
		ListNode* tail = tmp->pre;
		head->pre = tail;
		tail->next = head;
		free(tmp);

		tmp = head;
		head = head->next;
	}
	
	free(head);
	return true;
}

bool List::ClearList()
{
	ListNode* head = phead->next;
	ListNode* tmp = phead;
	while (head->next != head)
	{
		//ListNode* tmp = phead;
		ListNode* tail = tmp->pre;
		head->pre = tail;
		tail->next = head;
		free(tmp);

		tmp = head;
		head = head->next;
	}

	phead = head;
	return true;
}

ListNode* List::SearchList(ElemType search_value)
{
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == search_value)
		{
			return cur;
		}
		cur = cur->next;
	}
	return nullptr;
}

void List::InsertList(ElemType insert_value, int location)
{
	ListNode* cur = phead->next;
	for (int i = 0; i < location - 1; i++)
	{
		cur = cur->next;
	}
	//find the location of the node you want to insert
	//There, what you should pay attention to is the location difference between two node
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->data = insert_value;
	
	ListNode* pre_cur = cur->pre;
	pre_cur->next = newnode;
	newnode->pre = pre_cur;
	newnode->next = cur;
	cur->pre = newnode;
}

void List::ListPushFront(ElemType pushfront_value)
{
	ListNode* next_phead = phead->next;
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->data = pushfront_value;
	phead->next = newnode;
	newnode->pre = phead;
	newnode->next = next_phead;
	next_phead->pre = newnode;
}

void List::ListPopFront()
{
	ListNode* head_next = phead->next; // the node which needs to be delete
	ListNode* head_next_next = head_next->next;
	phead->next = head_next_next;
	head_next_next->pre = phead;
	free(head_next);
}

void List::DeleteList(int location)
{
	ListNode* cur = phead->next;
	//find the node you want to delete
	for (int i = 0; i < location - 1; i++)
	{
		cur = cur->next;
	}

	ListNode* pre_cur = cur->pre;
	ListNode* next_cur = cur->next;

	pre_cur->next = next_cur;
	next_cur->pre = pre_cur;
	free(cur);
}

bool CompareStr(string str1, string str2)
{
	int len1 = str1.length();
	int len2 = str2.length();
	if (len1 != len2)
	{
		return false;
	}
	else
	{
		int len = len1;
		string* pstr1 = &str1;
		string* pstr2 = &str2;
		for (int i = 0; i < len; i++)
		{
			if (*pstr1 != *pstr2)
			{
				return false;
			}
			pstr1++;
			pstr2++;
		}
	}
	return true;
}

int List::CalculateList(ElemType value_youfind)
{
	ListNode* cur = phead->next;
	int count = 0;
	while (cur != phead)
	{
		if (cur->data == value_youfind)
		{
			count++;
		}
	}
	return count;
}

这个头文件中的类就是链表的基本实现,可以在源文件中创建链表对象然后对其进行基本的操作。下面是源文件中的实现

#include"iostream"
#include"List.h"

using namespace std;

int main()
{
	//test the push element in the tail of the list
	//successfully
	List list;
	list.ListPushBack(1);
	list.ListPushBack(2);
	list.ListPushBack(3);
	list.ListPrint();
	

	//test clear the list
	/*list.ClearList();
	list.ListPrint();
	cout << endl;*/

	//judge if the function is successful 
	//in other word, judge if the function delete the phead pointer
	//successfully
	list.ListPushBack(4);
	list.ListPushBack(5);
	list.ListPushBack(6);
	list.ListPrint();
	
	
	//test the function which is used to find the value and return the node
	/*ListNode* find1 = list.SearchList(4);
	cout << find1->data << endl;*/

	

	//test the function which is used to delete the value which is in the tail of the list
	//successfully
	list.ListPopBack();
	list.ListPopBack();
	//list.ListPopBack();
	list.ListPrint();

	//test the function which is used to insert value in the postion you want
	//successfully
	list.InsertList(9, 2);
	list.InsertList(8, 2);
	list.ListPrint();


	list.ListPushFront(7);
	list.ListPushFront(7);
	list.ListPushFront(7);
	list.ListPrint();

	list.ListPopFront(); // successfully
	list.ListPopFront();
	list.ListPopFront();
	list.ListPrint();

	list.DeleteList(2);
	list.DeleteList(2);
	list.DeleteList(2);
	list.ListPrint();

	
	//test the function which is used to desroty the list head
	//means you can use the phead again unless you create the list again
	
	bool ifDes = list.DestoryList();
	cout << boolalpha << ifDes;
}

 这里我分了几段代码对接口函数进行测试,下面测试的结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值