数据结构-链表实现(单链表,双链表,类实现)

1.单链表

1)单的意思就是说只有一个方向,所以只能往一个方向增加节点

2)也因为单(身)所以处理起来很寂寞,注意几点吧:

    A)创建和遍历需要一个头节点(不含数据),和一个尾节点

    B)删除和插入都要在前一节点(比如要删除第二个节点,需要在第一个节点操作,又如在第三个节点前插入一个节点,得在第二个节点操作),所以后面类实现的成员函数一般都是找目标的前一节点。

类实现(创建,析构,删除,插入,输出)

/*by szu_crayon 2018/3/7*/
#include<iostream>
using namespace std;
class MyList
{
private:
	struct Node{
		int Data;
		Node* Next;
	};
	Node* Head;  //头节点
	Node* Tail;  //尾节点
public:
	MyList()    //创建头节点
	{
		Head = new Node;
		Head->Data = NULL; Head->Next = NULL;
		Tail = Head;
	}
	~MyList()    //释放链表空间
	{
		Node* Temp;
		while (Head)
		{
			Temp = Head;
			Head = Head->Next;
			delete Temp;
		}
	}
	void AddNode(int num)      //从尾部增加节点
	{
		Node *NewNode = new Node;
		NewNode->Data = num; NewNode->Next = NULL;    //增加节点的时候新节点后面没有元素所以next指向空
		Tail->Next = NewNode; Tail = NewNode;      //Tail连接新节点,然后新节点作为新的尾节点
	}
	int ListSize()           //返回链表元素个数
	{
		int cnt = 0;
		Node* Temp = Head;
		while (Temp->Next != NULL)
		{
			Temp = Temp->Next;
			cnt++;
		}
		return cnt;
	}
	Node* FindNode(int Index)         //返回所查找下标的前一个节点
	{
		Node* Temp = Head;
		int cnt = 0;
		while (Temp->Next != NULL)
		{
			cnt++;
			if (cnt == Index)
				return Temp;
			Temp = Temp->Next;
		}
		return NULL;     //no find
	}
	Node* FindNum(int num)     //返回查找数字所在节点的前一节点
	{
		Node* Temp = Head;
		while (Temp->Next != NULL)
		{
			if (Temp->Next->Data == num)
				return Temp;
			Temp = Temp->Next;
		}
		return NULL;     //no find
	}
	int DeleteNode(Node* FindedNode)    //删除指定位置的节点
	{
		if (FindedNode)
		{
			Node* Temp = FindedNode->Next;
			FindedNode->Next = Temp->Next;
			delete Temp;
			return 1;
		}
		return 0;
	} 
	void InsertNode(int Index,int num)          //指定位置插入一个数据为num的节点
	{
		if (Index - 1 == ListSize())    //如果指定位置刚好比链表元素多1,那么相当于在尾部增加节点
		{
			AddNode(num);
			PrintList();
		}
		else
		{
			Node *FindedNode = FindNode(Index);    //FIndedNode为插入位置的前一位
			if (FindedNode)
			{
				Node *NewNode = new Node;
				NewNode->Data = num; NewNode->Next = FindedNode->Next;
				FindedNode->Next = NewNode;
				PrintList();
			}
			else
				cout << "error" << endl;
		}
	}
	void PrintList()     //输出链表
	{
		int cnt = 1;
		Node *Temp = Head->Next;
		while (Temp)
		{
			if (cnt == 1)
				cout << Temp->Data;
			else
				cout << " " << Temp->Data;
			cnt++;
			Temp = Temp->Next;
		}
		//cout<<" " << endl;
		cout << endl;
	}
};

2.双向链表

1)在单向链表的基础上拥有前驱指针(指向前一个节点)。

2)友好,因为有指向前一节点的指针,说明插入删除只需查找当前需要插入或者删除的节点

3)还能逆序输出两端插入

4)因为我懒,所以功能实现没有前插和后插,其实可以把头节点删了换成一个头指针(就是指向有数据的第一个节点),这样就能实现前插后插,交给你们啦~

5)一个彩蛋,数据结构和STL相关,比如list就是以双链表为基础,所以下篇blog介绍List。

类实现(创建,析构,删除,插入,输出)


#include<iostream>
using namespace std;
struct Node
{
	int Data;
	Node* Prior;
	Node* Next;
};
class Double_direct_List
{
private:
	
	Node * Head;
	Node * Tail;
	int List_Size;
public:
	Double_direct_List();      //创建
	void AddNode(int Elem);     //尾插节点
	Node* Find_Elem(int Being_Find_Elem);   //查找含有指定数据的节点
	Node* Find_Index_Node(int Index);      //查找Index位置的节点
	int Delete_Node(Node* Finded_Node);     //删除节点
	int Insert_Node(int insert_index,int insert_Elem);    //插入含有数据insert_elem的节点
	int Get_ListSize();             //返回链表元素个数
	void Head_To_Tail_OutPut();   //顺序输出
	void Tail_To_Head_OutPut();   //逆序输出
};
Double_direct_List::Double_direct_List() :List_Size(0)
{
	Head = new Node;
	Head->Next = NULL; Head->Prior = NULL;
	Tail = Head;
}
void Double_direct_List::AddNode(int Elem)
{
	Node* NewNode = new Node;
	NewNode->Data = Elem;
	NewNode->Next = NULL;
	NewNode->Prior = Tail;    //比单向链表多了这一步,就是前驱指针要指向前一节点
	Tail->Next = NewNode;
	Tail = NewNode;
	List_Size++;
}
Node* Double_direct_List::Find_Elem(int Being_Find_Elem)
{
	Node* Index = Head->Next;
	while (Index)
	{
		if (Index->Data == Being_Find_Elem)
			return Index;
		Index = Index->Next;
	}
	return NULL;
}
Node* Double_direct_List::Find_Index_Node(int Index)
{
	Node* TempIndex = Head->Next;
	int cnt = 0;
	while (TempIndex)
	{
		if (++cnt == Index)
			return TempIndex;
		TempIndex = TempIndex->Next;
	}
	return NULL;
}
int Double_direct_List::Delete_Node(Node* Finded_Node)
{
	if (Finded_Node == NULL)
		return 0;
	Node* Prior_Node = Finded_Node->Prior;
	Node* Next_Node = Finded_Node->Next;
	Prior_Node->Next = Next_Node;
	if(Next_Node)
		Next_Node->Prior = Prior_Node;
	List_Size--;
	delete Finded_Node;
	return 1;
}
int Double_direct_List::Insert_Node(int insert_index, int insert_Elem)
{
	if (insert_index == List_Size+1)
		AddNode(insert_Elem);
	else
	{
		Node* Finded_Node = Find_Index_Node(insert_index);
		if (Finded_Node == NULL)
			return 0;
		else
		{
			Node* Prior_Node = Finded_Node->Prior;
			Node* NewNode = new Node;
			NewNode->Data = insert_Elem;
			Prior_Node->Next = NewNode;
			Finded_Node->Prior = NewNode;
			NewNode->Next = Finded_Node;
			NewNode->Prior = Prior_Node;
			List_Size++;
		}
	}
	return 1;
}
int Double_direct_List::Get_ListSize()
{
	return List_Size;
}
void Double_direct_List::Head_To_Tail_OutPut()
{
	int i=0;
	Node* TempHead = Head->Next;
	while (TempHead)
	{
		if (++i == 1)
			cout << TempHead->Data;
		else
			cout << " " << TempHead->Data;
		TempHead = TempHead->Next;
	}
	cout << endl;
}
void Double_direct_List::Tail_To_Head_OutPut()
{
	Node* TempTail = Tail;
	while (TempTail->Prior)
	{
		cout << TempTail->Data << " ";
		TempTail = TempTail->Prior;
	}
	cout << endl;
}

3.具体题目

(小傲娇放在最后没人看!)一道题:约瑟夫环(单链表实现),看完双链表可以用双链表实现下,附上题目及我代码的链接:点击打开链接

1.单链表的删除

1.问题描述

给出初始数据,实现单链表的定义、创建、查找和删除。假设单链表中的结点计数从1开始。

2.算法

单链表结点的存储结构包含两部分:数据、下一结点指针。

单链表的创建:依次为输入的数据分配结点,并按序链接起来。

单链表的查找:给出位置i,若第i个结点存在(1<=i<=表中结点数L),返回结点地址;否则,返回NULL。

单链表的删除:给出位置i,删除第i个结点(1<=i<=L)。

要求定义删除函数:int DeleteList(Node *H,int i) //删除第i个结点成功,返回1;第i个结点不存在,删除不成功,返回0。其中Node是链表结点结构体名,H是链表头指针。


每个样本分2行:

第一行:第一个数字n表示样本数目,其后跟n个样本

第二行:删除测试次数m 后跟m个删除位置

输出

第一行:单链表创建后,输出链表中元素个数和单链表中的全部数据。

第二行至第m+1行:若删除指定位置的数据成功,输出链表中元素个数和单链表中的全部数据;若删除不成功,输出error。

样例输入
5 2 4 3 5 7
3 0 2 4
样例输出
5 2 4 3 5 7
error
4 2 3 5 7
3 2 3 5
应用上述类实现代码
单链表实现
int main()
{
	int n, num;
	int t, Index;
	MyList OneList;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> num;
		OneList.AddNode(num);
	}
	cout << OneList.ListSize();
	OneList.PrintList();
	cin >> t;
	while (t--)
	{
		cin >> Index;
		if (OneList.DeleteNode(OneList.FindNode(Index)) )
		{
			cout << OneList.ListSize();
			OneList.PrintList();
		}
		else
			cout << "error" << endl;
	}
	return 0;
}
双向链表实现
int main()
{
	int size, deltime, delnum, num;
	Double_direct_List MyList;
	cin >> size;
	for (int i = 1; i <= size; i++)
	{
		cin >> num;
		MyList.AddNode(num);
	}
	cout << MyList.Get_ListSize();
	MyList.Head_To_Tail_OutPut();
	cin >> deltime;
	while(deltime--)
	{
		cin >> delnum;
		if (MyList.Delete_Node(MyList.Find_Index_Node(delnum) ) )
		{
			cout << MyList.Get_ListSize();
			MyList.Head_To_Tail_OutPut();
		}
		else
			cout << "error" << endl;
	}
	return 0;
}

2.单链表查找

1.问题描述

给出初始数据,实现单链表的定义、创建、查找。假设单链表中的结点计数从1开始。

2.算法

单链表结点的存储结构包含两部分:数据、下一结点指针。

单链表的创建:依次为输入的数据分配结点,并按序链接起来。

单链表结点个数L(也称单链表表长L):从头至尾遍历单链表,对结点进行计数。

单链表的查找:给出位置i,若第i个结点存在(1<=i<=L),返回结点地址;否则,返回NULL。

要求查找子函数定义为:Node *Find(Node *H,int i)

//若i的值在1...单链表长L之间,返回第i个结点的地址;否则返回空指针NULL。其中Node为链表结点结构体名,H为链表头指针。

输入

每个样本分2行:

第一行:第一个数字n表示样本数目,其后跟n个样本。

第二行:查找测试次数m 后跟m个待查找的位置。

输出

第一行:单链表创建后,输出链表中元素个数和单链表中的全部数据。

第二行到第n+1行,对每个查找位置,若结点存在,输出结点数据;否则输出error。

样例输入
6 1 2 3 4 5 64 0 2 10 6
样例输出
6 1 2 3 4 5 6
error
2
error
6

应用上述类实现代码
单向链表实现
int main()
{
	MyList OneList;
	int n, num;
	int t, Index;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> num;
		OneList.AddNode(num);
	}
	cout << OneList.ListSize();
	OneList.PrintList();
	cin >> t;
	while (t--)
	{
		cin >> Index;
		if (OneList.FindNode(Index))
			cout << OneList.FindNode(Index)->Next->Data<< endl;
		else
			cout << "error" << endl;
	}
	return 0;
}
双向链表实现
int main()
{
	int size, TxTtime, testindex, num;
	Double_direct_List MyList;
	cin >> size;
	for (int i = 1; i <= size; i++)
	{
		cin >> num;
		MyList.AddNode(num);
	}
	cout << MyList.Get_ListSize()<<" ";
	MyList.Head_To_Tail_OutPut();
	cin >> TxTtime;
	while (TxTtime--)
	{
		cin >> testindex;
		Node* FindedNode = MyList.Find_Index_Node(testindex);
		if (FindedNode)
			cout << FindedNode->Data << endl;
		else
			cout << "error" << endl;
	}
	return 0;
}

3.单链表插入

1.问题描述

单链表初始为空,给定插入位置和数据,插入结点实现单链表的创建。假设单链表中的结点计数从1开始。

2.算法

单链表结点的存储结构包含两部分:数据、下一结点指针

单链表的查找:给出位置i,若第i个结点存在(1<=i<=表中结点数L),返回结点地址;否则,返回NULL。

单链表的插入:给出位置i和数据e,在单链表第i(1<=i<=L+1)个结点位置插入新结点,数据为e。

输入

测试次数n

每行一组测试数据,格式如下:

位置i 数据e

输出

对每组测试数据,调用插入函数在位置i插入数据e,若插入成功,输出当前链表中的数据;若插入不成功,输出error。

样例输入
80 10
1 10
2 20
3 30
1 40
6 60
5 50
9 100
样例输出
error
10
10 20
10 20 30
40 10 20 30
error
40 10 20 30 50
error
应用上述类实现代码
单向链表实现
int main()
{
	MyList OneList;
	int t, Index, num;
	cin >> t;
	while (t--)
	{
		cin >> Index >> num;
		OneList.InsertNode(Index, num);
	}
	return 0;
}
双向链表实现
int main()
{
	Double_direct_List MyList;
	int insert_time, insert_data, insert_index;
	cin >> insert_time;
	while (insert_time--)
	{
		cin >> insert_index >> insert_data;
		if (MyList.Insert_Node(insert_index, insert_data))
		{
			MyList.Head_To_Tail_OutPut();
			MyList.Tail_To_Head_OutPut();
		}
		else
			cout << "error" << endl;
	}
	
	return 0;
}

还有一道题:约瑟夫环,看完双链表可以用双链表实现下,附上题目及我代码的链接:点击打开链接




感觉没有注释是不是和没缩减对齐一样是渣男~


猜你喜欢

转载自blog.csdn.net/szu_crayon/article/details/79831580
今日推荐