2 数据结构与算法之线性表

1 线性表(list):由零个或多个数据元素组成的有序序列(第一个元素无前驱,最后一个元素无后继,中间的元素有且仅有一个前驱和后继)
在这里插入图片描述
1.1 线性表的顺序存储结构
在这里插入图片描述
在这里插入图片描述
实现两个线性表A,B的并集操作即使得A=AUB

/*La表示A集合,Lb表示B集合*(C语言实现)/
void unionL(List *La,list Lb)
{
i
	ElemType e;
	La_len = ListLength(*La);
	Lb_len = ListLength(Lb);

	for(i=1;i<=Lb_len;i++)
	{
		GetElem(Lb,i,&e);
		if(!LocateElem(*La,e))
		{
			ListInsert(La,++La_len,e);
		}
	}

}

/*******************getElem.c*********************/
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
//Status 是函数的类型,其值是函数结果状态代码,如OK等
//初始条件:顺序线性表L已经存在,1 <= i <=ListLength(L)
//操作结果:用e返回L中第i个数据元素的值

Status GetElem(SpList L,int i,ElemType *e)
{
	if(L.length==0||i<1||i>L.length)
	{
		return ERROR;
	}
	*e = L.data[i-1];
	return OK;
}

/****************************ListInsert.c********************************/
Status ListInsert(SpList *L,int i,ElemType e)
{
	if(L.length==MAXSIZE||i<1||i>L.length+1)//顺序表满了或者i不在范围内时
	{
		return ERROR;
	}
	if(i<=L->length)//如插入的数据位置不在表尾
	{
	    /*将要插入位置后数据元素想后移动一位*/
	 	for(int k=L->length-1;k>=i-1;k--)//????
	 	{
	 		L->data[k+1] = L->data[k];
	 	}
	}
		L->data[i-1]=e;
		L->length++;
		return OK;
}
/**********************************ListDelete.c***********************************/
ListDelete(SpList *L,int i ,ElemType *e)
{
	if(L->length==0)//空队列
	{
		return ERROR;
	}
	if(L->length<1||L->length+1)//i不在范围内
	{
	    return ERROR;
	}
	if(i<L->length)//删除的元素后面的元素全部往前移动一位
	{
			for(int k=i;  k<L->length;k++)//????
			{
				L->data[k-1]=L->data[k];
			}
	}
	*e=L->data[i-1];
	L->length--;
	return OK;
}

删除和插入的事件复杂度
最好的情况:刚好在线性表最后一个O(1)
最坏的情况:刚好在线性表的第一个O(n)
平均值:O((n-1)/2)=O(n)
结论:线性表的顺序存储结构,在存,读数据时,不管是哪个位置,事件复杂度都是O(1);在插入或者删除时,事件复杂度都是O(n)。
在这里插入图片描述
1.2 线性表的链式存储结构

在这里插入图片描述

单链表C++实现代码

/*****************Node.h****************************/
#pragma once
#include"Person.h"
class Node
{
public :
	Person data;
	Node *next;

	void printNode();
};

/*********************Node.cpp*************************/
#include "Node.h"
#include<iostream>
#include"Person.h"
using namespace std;
void Node::printNode()
{
	cout << data << endl;
}

/*******************List.h***************************/
#pragma once

#include<iostream>
#include"Node.h"
using namespace std;


class List
{
public:
	List();
	~List();
	void ClearList();                                  //清空线性表
	bool ListEmpty();                                  //判断线性表是否为空 
	int ListLength();                                  //获取线性表的长度
	bool GetElem(int i,Node *pNode);                             //获取指定元素
	int LocateElem(Node *pNode);                          //寻找第一个满足e的数据元素的位序
	bool PriorElem(Node *currentElem, Node *preElem);  //获取指定元素的前驱
	bool NextElem(Node *currentElem, Node *nextElem);  //获取指定元素的后驱
	bool ListInsert(int i, Node *pNode);                   //在第i个位置插入元素
	bool ListDelete(int i, Node *pNode);                   //在删除第i个位置的元素
	void ListTraverse();                 //遍历线性表
	bool ListInsertHead(Node *pNode);               //头插法
	bool ListInsertTail(Node *pNode);               //尾插法

private:
	
	int m_iLength;
	Node *m_pList;
};
/**************************************List.cpp*********************************/

#include "List.h"
#include"Node.h"
#include <iostream>
using namespace std;


List::List()
{           
	m_pList = new Node;   
	//m_pList->data = 0;     //头结点  数据域没有意义
	m_pList->next = NULL;     
	m_iLength = 0;
}


List::~List()
{
	ClearList();
	delete m_pList;
	m_pList = NULL;
}

bool List::ListInsertHead(Node *pNode)              //头插法:将一个节点插入到头结点的后面
{
	Node *temp = m_pList->next;        //申请一个零时内存来存放头结点的头指针,必须从堆中申请内存,从栈中申请的话,这个函数用完后就会被回收
	Node *newNode = new Node;          //申请一个节点来存放要插入的节点
	if (newNode == NULL)
	{
		return false;
	}
	newNode->data = pNode->data;
	m_pList->next = newNode;
	newNode->next = temp;     //新节点尾部指向NULL

	m_iLength++;
	return true;
}
bool List::ListInsertTail(Node *pNode)              //尾插法将新节点插入到list的尾部
{
	Node *currentNode = m_pList;
	while (currentNode->next!=NULL)
	{
		currentNode = currentNode->next;
	}
	Node *newNode = new Node;
	if (newNode == NULL)
	{
		return false;
	}
	newNode->data = pNode->data;
	newNode->next = NULL;
	currentNode->next = newNode;
	m_iLength++;
	return true;
}

void List::ClearList()                                  //清空线性表
{
	Node *currentNode = m_pList->next;              //currentNode获取头结点所指的下一位
	while (currentNode != NULL)
	{
		Node *temp = currentNode->next;            //
		delete currentNode;
		currentNode = temp;
	}
	m_pList->next = NULL;
}


bool List::ListEmpty()                                 //判断线性表是否为空
{
	return m_iLength == 0 ? true : false;

}


int List::ListLength()                                  //获取线性表的长度
{
	return	m_iLength;
}


bool  List::GetElem(int i, Node *pNode)                      //获取指定元素
{
	if (i < 0 || i >= m_iLength)
	{
		return false;
	}
	Node *currentNode = m_pList;      //currentNode 赋值为头结点
	//Node *currentNodeBefore = NULL;
	for (int k = 0; k <= i; k++)
	{
		//currentNodeBefore = currentNode;
		currentNode = currentNode->next;
	}
	pNode->data = currentNode->data;

	return true;
}


int  List::LocateElem(Node *pNode)                     //寻找第一个满足e的数据元素的位序
{
	Node *currentNode = m_pList;
	int count = 0;
	while (currentNode!=NULL)
	{
		currentNode = currentNode->next;
		if (currentNode->data == pNode->data)
		{
			return count;
		}
		count++;
	}
	return -1;
}


bool  List::PriorElem(Node *pCurrentNode, Node *pPreNode)  //获取指定元素的前驱
{
	Node *currentNode = m_pList;
	Node *tempNode = NULL;
	while (currentNode != NULL)
	{
		tempNode = currentNode;
		currentNode = currentNode->next;
		if (currentNode->data == pCurrentNode->data)
		{
			if (tempNode == m_pList)
			{
				return false;
			}
			pPreNode->data = tempNode->data;
		}
		return true;
	}
	return false;
}



bool  List::NextElem(Node *pCurrentNode, Node *pNextNode)  //获取指定元素的后驱
{

	Node *currentNode = m_pList;
	while (currentNode != NULL)
	{
		currentNode = currentNode->next;
		if (currentNode->data == pCurrentNode->data)
		{
			if (currentNode == m_pList)
			{
				return false;
			}
			pNextNode->data = currentNode->next->data;
		}
		return true;
	}
	return false;

}


bool  List::ListInsert(int i, Node *pNode)                   //在第i个位置插入元素
{
	if (i<0 || i>m_iLength)
	{
		return false;
	}
	Node *currentNode = m_pList;
	for (int k = 0; k < i; k++)
	{
		currentNode = currentNode->next;
	}
	Node *newNode = new Node;
	if(newNode==NULL)
	{
		return false;
	}
	newNode->data = pNode->data;
	newNode->next = currentNode->next;
	currentNode->next = newNode;
	return true;
}


bool  List::ListDelete(int i, Node *pNode)                   //在删除第i个位置的元素,并把删除元素的值通过pNode返回出来
{
	if (i < 0 || i >= m_iLength)
	{
		return false;
	}
	Node *currentNode = m_pList;
	Node *currentNodeBefore = NULL;
	for (int k = 0; k <= i; k++)
	{
		currentNodeBefore = currentNode;
		currentNode = currentNode->next;     //循环结束:currentNode为待删除的节点,currentNodeBefore为待删除节点的前一位
	}
	currentNodeBefore->next = currentNode->next;  //currentNodeBefore指向删除节点后的节点
	pNode->data = currentNode->data;
	delete currentNode;                       //删除节点
	currentNode = NULL;      
	m_iLength--;
	return true;
}

void  List::ListTraverse()                 //遍历线性表s
{
	Node *currentNode = m_pList;
	while (currentNode->next != NULL)
	{
		currentNode = currentNode->next;
		currentNode->printNode();
	}
}

/***************person.h***********/
#pragma once
#include<string>

using namespace std;

class Person
{
	friend ostream &operator<<(ostream &out,Person &person);
public:
	string name;
	string phone;
	Person &operator=(Person &person);
	bool operator==(Person &person);
};

/******************person.cpp******************/
#include"Person.h"
Person &Person::operator=(Person &person)
{
	name = person.name;
	phone = person.phone;
	return *this;
}

bool Person :: operator==(Person &person)
{
	if (this->name == person.name&&this->phone == person.phone)
	{
		return true;
	}
	return false;
}

 ostream &operator<<(ostream &out, Person &person)
{
	 out << person.name << "---------" << person.phone << endl;
	 return out;
}

/**************************demo.cpp****************************/
#pragma once
#include"List.h"
#include"Node.h"
#include <iostream>
int main(void)
{
	Node node1;
	Node node2;
	node1.data .name= "test";
	node1.data.phone = "123456";

	node2.data.name = "test1";
	node2.data.phone = "12345697";

	List *pList = new List();

	//pList->ListInsert(0,&node1);
	pList->ListInsertHead(&node1);
	pList->ListInsertHead(&node2);

	
	pList->ListTraverse();
	
	
	delete pList;
	pList = NULL;
	system("pause");
	return 0;
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值