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

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

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

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

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

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

对于单链表

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

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

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

应用场景选择

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

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

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

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;
}
时间: 2024-11-18 23:03:39

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

单链表的基础操作

单链表中节点的查找.插入.删除.求单链表长度等操作. 按序号查找结点值 在单链表中从第一个结点出发,顺指针next域逐个往下搜索,直到找到第i个结点为止,否则返回最后一个结点指针域NULL. 按序号查找结点值的算法如下: LNode GetElem(LinkList L,int i){ //本算法取出单链表L(带头结点)中第i个位置的结点指针 int j=1; //计数,初始为1 LNode *p = L->next; //头结点指针赋给p if(i==0) return L; //若i等于0,

Java数据结构——单链表

一.单链表的概念 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.这组存储单元可以是连续的,也可以是不连续的. 存储单元由两部分组成,数据源和指针,数据源放数据,指针指向下个存储单元. 二.单链表的结构 采用Node实体类类标识,其中data为存储的数据,next为下一个结点的指针. //链表的实体类 class Node{ public int data; public Node next; public Node(int data) { this.data =

python实现数据结构单链表

#python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" def __init__(self, elem): self.elem = elem self.next = None # 节点一开始初始化的时候并不知道下一个元素的地址,所以先设置为空 class SingLinkList(object): """单链表""

数据结构之自建算法库——单链表

本文针对数据结构基础系列网络课程(2):线性表中第10课时单链表基本操作的实现,建立单链表数据存储结构基本操作的算法库. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 单链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:linklist.h,包含定义顺序表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef LINKLIST_H_INCLUDED #define LINKLIST_H_INCLUDED typedef

数据结构关于单链表的一些操作的源代码

单链表的可以有许多问题,这是我特意整理一下的有关他的相关操作,给出代码,有需要的可以自己调试,重要的就是关于环的一些操作: #include <iostream>#include <cstdio>#include <cstdlib>#include <ctime>using namespace std;typedef int Elemtype;typedef struct Node{ Elemtype data; struct Node *next;}Nod

数据结构——单链表及其操作

1 #include<iostream> 2 #include<string> 3 #include<stdlib.h> 4 5 using namespace std; 6 7 typedef int ElemType; 8 typedef int Status; 9 #define OK 1 10 #define ERROR 0 11 12 13 //单链表的存储结构 14 typedef struct LNode 15 { 16 ElemType data; //

python数据结构与算法之单链表

表的抽象数据类型 ADT list:                      #一个表的抽象数据类型 List(self)               #表的构造操作,创建一个空表 is_empty(self)        #判断self是否为一个空表 len(self)                #获得self的长度 prepend(self, elem)         #将元素elem加入表中作为第一个元素 append(self, elem)           #将元素elen

C:数据结构与算法之单链表

单链表相对于顺序表比较难理解,但是比较实用,单链表的插入,删除不需要移动数据元素,只需要一个指针来寻找所需要的元素,还有一个大优点就是不浪费空间,当你想要增加一个结点可以申请(malloc())一个结点的空间,删除一个结点也可以释放(free()),跟顺序表一样的,首先先来定义一个单链表, 1 typedef struct lnode 2 { 3 int data; 4 struct lnode *next; 5 }LNode,*LinkList; typedef是将类型struct lnode

C# 数据结构 - 单链表 双链表 环形链表

链表特点(单链表 双链表) 优点:插入和删除非常快.因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作. 缺点:当需要查找某一个节点的时候就需要一个节点一个节点去访问,这样所花的时候就比较多了.(顺序表可以弥补这缺点,但插入和删除就非常耗性能) 单链表 单链表的构成:必须要有一个链表头(head),每个节点里面有一个Next用于指向下一个节点(类似于指针).最后一个节点的Next为null来标识链表的尾. 如下图 代码实现 1 /* ----