算法数据结构 单链表的实现+操作 以及和顺序表的对比

16 篇文章 0 订阅
16 篇文章 0 订阅

顺序表和单链表的优缺点对比:

顺序表的优点,无需为表示表中元素之间的逻辑关系而增加额外的存储空间

可以快速的存取表中的任意位置的元素

顺序表的缺点,插入后删除操作需要移动大量元素

当线性表长度不稳定时,存储空间难确定容易造成存储空间碎片。


对于单链表

链式存储即元素存储的内存单元可以是不连续,分散的。对于元素间如何来维护他们的关系(即逻辑结构,每个元素的前驱和后继。)

即用到一个指针域来存储他和前驱或是后继直接的关系。

如上面的是一个单链表的指针结构,即每个元素中存储了他的后继元素的内存空间地址。


应用场景选择

由上图可以简单的知道数据的常见的操作,增,删,改,查时。

对于数据操作偏向于查和改时,顺序存储的速度是非常快的,而链表的话,则必须从头节点开始遍历查找。

但是涉及到插入或是删除元素时,顺序存储每次操作为了维护顺序,必须移动元素,而对于链表来说,只需新增一个存储单元后,对其中几个指针域中指针的指向做下改变就行。

tips1. 但是我们要注意的是, 表的插入和删除操作其实有两部分组成:遍历找到第i个元素,然后删除或插入。那其实顺序表这步的时间复杂度为 O(1),

而单链表的时间复杂度为O(n),虽然后面的话顺序表需要将i后面的元素都往后移动一位,话费的时间相对来说就是O(n),而单链表无需移动元素,

时间就为O(1)。看上去其实貌似扯平啊,这样单链表相对于线性表的顺序存储结构来说没什么大的优势。但是如果在第i点插入k个元素时,

那么相对于链表来说只要第一遍历查找到了第i个元素后,之后的操作基本是是O(1),而顺序的操作的话,是每次都要移动n-i个元素,O(n),

效果就出来了。

tips2.而对于顺序表,如果我们的插入和删除操作,在不考虑存储空间额分配这个死角的话(即存储空间可以动态的申请,不考虑溢出),

都是在对最后的一个元素进行操作,那不是也很好,即删除和插入都是在表尾进行,那么就不用移动大量元素了。



代码实现:


#ifndef _LIST_H
#define _LIST_H

#include<iostream>
#include<assert.h>//断言
#include<string.h>
#include<stdlib.h>
#include<malloc.h>


#include<iostream>
using namespace std;

#define ElemType int

typedef struct Node
{
	ElemType data;
	struct Node *next;
}Node, *PNode;

typedef PNode List;


/*-------------------------函数声明------------------------*/
void menu();//菜单
void InitList(List *list);//初始化函数
bool CreateList(List *list, int count);//创建函数
bool isEmpty(List *list);//判断空
bool push_front(List *list, ElemType x);//头插
int push_back(List *list, ElemType x);//尾插
bool pop_front(List *list);//头删
bool pop_back(List *list);//尾删
Node* find(List *list, ElemType x);//查询 返回输入序号的指针
int	LocatePos(List *list, ElemType x);//查询 获取输入序号的值
void Length(List *list);//长度
bool delete_pos(List *list, ElemType pos);//位置删除
bool delete_val(List *list, ElemType x);//值删
bool modify(List *list, int pos, ElemType x);//修改某位置的值域
bool DestroyList(List *list);//摧毁
void ShowList(List list);//显示
bool insert_pos(List *list, int pos, ElemType x);//位置插入
bool insert_val(List *list, ElemType x);//值 插入(有序前提)
bool sort(List *list);//排序
Node* resver(List *list);//逆置
void reverse_2(List *list);//逆置
Node* next(List *list, ElemType key);//返回输入位置的后继节点
Node* prio(List *list, ElemType key);//返回输入位置的前驱节点
Node* Pfind(List *list, size_t pos);//返回对应位置的指针



#endif





#include"List.h"



/*-----------------函数实现部分----------------------*/
void menu()
{
	cout << "								   " << endl;
	cout << "**********************************" << endl;
	cout << "* [100] CreateList               *" << endl;
	cout << "* [0] quit_system [1] push_back  *" << endl;
	cout << "* [2] push_front  [3] show_list  *" << endl;
	cout << "* [4] pop_back    [5] pop_front  *" << endl;
	cout << "* [6] insert_pos				 *" << endl;
	cout << "* [8] delete_pos  [9] delete_val *" << endl;
	cout << "* [10] find       [11] LocatePos *" << endl; 
	cout << "* [12] modify     [13] destroy   *" << endl;
	cout << "* [14] sort       [15] resver    *" << endl;
	cout << "* [16] length     [17] next      *" << endl;
	cout << "* [18] prio                      *" << endl;
	cout << "**********************************" << endl;
	cout << "plese chose:>";
}

/*-----------初始化单链表———————————————*/
void InitList(List *list)
{
	*list = (Node *)malloc(sizeof(Node));
	(*list)->next = NULL;
	(*list)->data = 0;
}

/*---------头节点的方式创建单链表---------------------*/
//???????
bool CreateList(List *list,int count) //Node * *list
{
	Node *p = *list;
	ElemType x = 0;
	for (int i = 1; i <= count; ++i)
	{
		cin >> x;
		p = p->next = (Node *)malloc(sizeof(Node));
		p->data = x;
		p->next = NULL;
		(*list)->data++;
	}
	return false;
}

/*----判断空--------*/
bool isEmpty(List *list)
{
	return (NULL == (*list)->next);
}


/*-----------------尾插————————————*/
int push_back(List *list, ElemType x)
{
	if (isEmpty(list))
		return 0;
	Node* cur = (*list)->next;
	while (cur->next != NULL)
	{
		cur = cur->next;
	}
	Node *p = (Node *)malloc(sizeof(Node));
	if (p == NULL)
		return 0;
	p->data = x;
	cur->next = p;
	p->next = NULL;

	(*list)->data++;
}

/*-----------------头插————————————*/
bool push_front(List *list, ElemType x)
{
	Node *p = (Node *)malloc(sizeof(Node));
	if (p == NULL)
		return false;
	p->data = x;
	p->next = (*list)->next;
	(*list)->next = p;

	(*list)->data++;
}


/*------显示--------------*/
void ShowList(List list)
{
	Node *p = list->next;
	while (p != NULL)
	{
		cout << p->data << "-->";
		p = p->next;
	}
	cout << "Nul" << endl;
}

/*-----------------尾删————————————*/
bool pop_back(List *list)
{
	if (isEmpty(list))
		return false;
	Node* cur = (*list);
	while (cur->next != NULL && cur->next->next != NULL)
	{
		cur = cur->next;
	}
	free(cur->next);
	cur->next = NULL;
	(*list)->data--;
	return true;
}



/*-----------------头删————————————*/
bool pop_front(List *list)
{
	if (isEmpty(list))
		return false;
	Node *p = (*list)->next;
	(*list)->next = p->next;
	free(p);
	p = NULL;
	(*list)->data--;
}


/*-------------------按位置插入--------------*/
bool insert_pos(List *list, int pos, ElemType x)
{
	Node *p = Pfind(list, pos - 1);//寻找第i-1个结点
	if (p == NULL)//i<1或i>n+1时插入位置i有错
	{
		cout << "ERROR POS" << endl;
	}
		Node* s = (Node *)malloc(sizeof(Node));
		s->data = x;
		s->next = p->next; 
		p->next = s;
	return false;
}


/*--------位置删除---------------*/
bool delete_pos(List *list, ElemType pos)
{
	int count = 1;
	Node* cur = NULL;
	Node* pre = *list;
	while (pre->next != NULL && pre->next->next != NULL && count < pos)//找到前驱
	{
		pre = pre->next;
		count++;
	}
	if (count != pos)
	{
		cout << "ERROE pos" << endl;
		return false;
	}
	cur = pre->next;
	pre->next = cur->next;
	free(cur);
	cur = NULL;
	(*list)->data--;
	return  true;
}


/*----------按值删除-------------*/
bool delete_val(List *list, ElemType x)
{

	Node* pre = *list;
	Node* cur = NULL;
	while (pre->next != NULL && pre->next->next != NULL)//找到前驱
	{
		if (x == pre->next->data)
		{
			cur = pre->next;
			pre->next = cur->next;
			free(cur);
			cur = NULL;
			return true;
		}
		pre = pre->next;
	}
	(*list)->data--;
	return true;
}

/*----------------查询 返回指针————————————*/
Node* find(List *list, ElemType x)
{
	Node *p = (*list)->next;
	while (p)
	{
		if (p->data != x)
			p = p->next;
		else
			break;
	}
	return p;
}

/*----------输入序号 返回指针——————*/
Node* Pfind(List *list, size_t pos)
{
	size_t count = 1;
	Node *p = (*list)->next;
	while (count < pos)
	{
		p = p->next;
		count++;
	}

	if (count != pos)
		return NULL;
	return p;	
}

/*-----------------查询 返回序号————————————*/
int	LocatePos(List *list, ElemType x)
{
	Node* cur = (*list)->next;
	int count = 0;
	while (cur)
	{
		count++;
		if (x == cur->data)
			return count;    //返回是第几个元素
		cur = cur->next;
	}
	return 0;
}


/*--------------修改---------------*/
bool modify(List *list,int pos, ElemType x)
{
	int count = 1;
	if (pos < 0 || pos >(*list)->data)
		return false;
	Node* cur = (*list)->next;
	while (cur != NULL && cur->next != NULL)
	{
		if (count == pos)
		{
			cur->data = x;
			return true;
		}
		cur = cur->next;
		count++;
	}
	return false;
}

/*-------销毁-------------*/
bool DestroyList(List *list)
{
	Node *p = (*list);
	Node *q = NULL;
	while (p)
	{
		q = p->next;
		free(p);
		p = q;
	}
	(*list)->next = NULL;
	cout << "the List was destroyed !" << endl;
	cout << "After destroy ,any operation is invalid!" << endl;
	cout << "Please quit_system!" << endl;
	return true;
}

/*----------排序--------------*/
bool sort(List *list)
{
	if (isEmpty(list))
		return false;
	Node* p = NULL;
	Node* q = NULL;
	for (p = (*list)->next; p != NULL; p = p->next)
	{
		for (q = p->next; q != NULL; q = q->next)
		{
			if (p->data > q->data)
			{
				p->data = p->data   ^    q->data;
				q->data = p->data   ^    q->data;
				p->data = p->data   ^    q->data;
			}
		}
	}
	return true;
}


/*-------逆置-----------*/
Node* resver(List *list)
{
	Node *p = (*list)->next;
	Node *q = NULL;
	Node *r = NULL;

	while (p)
	{
		q = p->next;
		p->next = r;
		r = p;
		p = q;
	}
	
	return r;
}

void reverse_2(List *list)
{
	Node *p, *q;
	p = (*list)->next;    //P指向链表第一个元素  
	(*list)->next = NULL; //断开头结点与链表  
	while (p != NULL)
	{
		q = p;
		p = p->next;
		q->next = (*list)->next;  //相当于前插法构建新的链表,和原来的相反  
		(*list)->next = q;
	}
}


/*----------------返回长度————————————*/
void Length(List *list)
{
	cout << "the length of list is:>" << (*list)->data << endl;
}

/*-----------------返回后继————————————*/
Node* next(List *list, ElemType key)  //输入节点序号返回其后继节点
{
	Node* cur = (*list)->next;
	int count = 1;

	if (isEmpty(list) || key < 0 || key > (*list)->data)
		return false;

	while (count < key)
	{
		cur = cur->next;
		count++;
	}
	if (count == key)
	{
		cur = cur->next;
		return cur;
	}
	else
	{
		cout << "ERROE" << endl;
		return false;
	}
}


/*-----------------返回前驱————————————*/
Node* prio(List *list, ElemType key)
{
	Node* pre = (*list);
	Node* cur = (*list)->next;
	int count = 1;
	if (isEmpty(list) || key < 1 || key > (*list)->data)
		return false;
	while (count < key)
	{
		pre = pre->next;
		cur = cur->next;
		count++;
	}
	if (count == key)
	{
		return pre;
		
	}
	else
	{
		cout << "ERROE" << endl;
		return false;
	}
}


#include"List.h"

int main(void)
{

	List mylist;
	InitList( &mylist);
	
	ElemType item;
	int pos = 0;
	int select = 1;
	int length = 0;

	

	while (select)
	{
		menu();
		cin >> select;
		switch (select)
		{

		case 100:
			cout << "please input the length:>" ;
			cin >> length;
			cout << "please input the data:>" ;
			CreateList(&mylist, length);
			
			break;

		case 1:
			cout << "please enter data:>";
			cin >> item;
			push_back(&mylist, item);
			break;

		case 2:
			cout << "please enter data:>";
			cin >> item;
			push_front(&mylist, item);
			break;

		case 3:
			ShowList(mylist);
			break;

		case 4:
			pop_back(&mylist);
			break;

		case 5:
			pop_front(&mylist);
			break;

		case 6:
			cout << "please enter position:>";
			cin >> pos;
			cout << "please enter insert data:>";
			cin >> item;
			insert_pos(&mylist, pos, item);
			break;


		case 8:
			cout << "please enter position:>";
			cin >> pos;
			delete_pos(&mylist, pos);
			break;

		case 9:
			cout << "please enter delete data:>";
			cin >> item;
			delete_val(&mylist, item);
			break;

		case 10:
			cout << "please enter data:>";
			cin >> item;
			cout << "the piont of pos is:>" << find(&mylist, item) << endl;
			break;

		case 11:
			cout << "please enter data:>";
			cin >> item;
			cout << "the number of pos is>" << LocatePos(&mylist, item)<< endl;
			break;

		case 12:
			cout << "please enter position:>";
			cin >> pos;
			cout << "please enter the modify data:>";
			cin >> item;
			modify(&mylist, pos, item);
			break;


		case 13:
			DestroyList(&mylist);
			break;

		case 14:
			sort(&mylist);
			cout << "the changes of SeqList will be incremental ! " << endl;
			ShowList(mylist);
			break;

		case 15:
			(mylist)->next = resver(&mylist);
			cout << "the changes of List will be resver ! " << endl;
			ShowList(mylist);
			reverse_2(&mylist);
			cout << "the changes of List will be resver ! " << endl;
			ShowList(mylist);
			break;

		case 16:
			Length(&mylist);
			break;

		case 17:
			cout << "please enter position:>";
			cin >> pos;
			if (pos <= 0 || pos >= (mylist)->data)//保证输入位置正确
			{
				cout << "ERROR POS" << endl;
				break;
			}

			cout << "the NextPosData is:>" << next(&mylist, pos)->data;
			break;


		case 18:
			cout << "please enter position:>";
			cin >> pos;
			if (pos <= 1 || pos > (mylist)->data)//保证输入位置正确
			{
				cout << "ERROR POS" << endl;
				break;
			}

			cout << "the PrePosData is:>" << prio(&mylist, pos)->data;
			break;

		

		}

	}

	return 0;
}







  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值