【数据结构与算法003】基本数据结构——线性表(链表)
2016-11-04 16:55
916 查看
线性表分为顺序表(数组)和链表,其中链表包括静态链表(对于有些计算语言没有指针)、单链表、循环链表和双向链表,我们主要学习单链表。
顺序表的优点:在进行遍历和寻址的时候非常快速,效率很高。
缺点:显而易见,当我们想往顺序表中插入一个元素的时候,当前位置向后的所有元素都要向后移动一个位置,这样数据才能顺利地插入进去,删除时同理。那么如何才能避免现象呢?我们需要用到链表。
链表节点Node.h
链表节点Node.cpp
顺序表List.cpp
#ifndef PERSON_H
#define PERSON_H
#include <string>
#include <ostream>
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); //重载比较运算符
};
#endifPerson.cpp
一、顺序表的基本操作
首先看一下线性顺序表的基本操作List.h#ifndef LIST_H #define LIST_H /************************************************************************/ /* 线性表--顺序表 3 5 7 2 9 1 8 前驱 后继 BOOL InitList(List **list); //创建线性表 void DestroyList(List *list); //销毁线性表 void ClearList(List *list); //清空线性表 BOOL ListEmpty(List *list); //判断线性表是否为空 int ListLength(List *list); //获取线性表长度 BOOL GetElem(List *list,int i,Elem *e); //获取指定元素 int LocateElem(List *list,Elem *e); //寻找第一个满足e的数据元素的位序 BOOL PriorElem(List *list,Elem *currentElem,Elem *preElem); //获取指定元素的前驱 BOOL NextElem(List *list,Elem *currentElem,Elem *nextElem); //获取指定元素的后继 BOOL ListInsert(List *list,int i,Elem *e); //在第i个位置插入元素 BOOL ListDelete(List *list,int i,Elem *e); //在删除第i个位置的元素 void ListTraverse(List *list); //遍历线性表 */ /************************************************************************/ class List{ public: List(int size); ~List(); void ClearList(); bool ListEmpty(); int ListLength(); bool GetElem(int i, int *e); int LocateElem(int *e); bool PriorElem(int *currentElem, int *preElem); bool NextElem(int *currentElem, int *nextElem); void ListTraverse(); bool ListInsert(int i, int *e); bool ListDelete(int i, int *e); private: int *m_pList; int m_iSize; int m_iLength; }; #endifList的具体实现List.cpp
#include "List.h" #include <iostream> using namespace std; List::List(int size){ m_iSize = size; m_pList = new int[m_iSize]; m_iLength = 0; } List::~List(){ delete[]m_pList; m_pList = NULL; } void List::ClearList(){ m_iLength = 0; } bool List::ListEmpty(){ if (m_iLength == 0) { return true; } else { return false; } //return m_iLength == 0 ? true : false; } int List::ListLength(){ return m_iLength; } bool List::GetElem(int i, int *e){ if (i < 0 || i >= m_iSize) { return false; } *e = m_pList[i]; return true; } int List::LocateElem(int *e){ for (int i = 0; i < m_iLength; i++) { if (m_pList[i] == *e) { return i; } } return -1; } bool List::PriorElem(int *currentElem, int *preElem){ int temp = LocateElem(currentElem); if (temp == -1 || temp == 0) { return false; } else { *preElem = m_pList[temp - 1]; return true; } } bool List::NextElem(int *currentElem, int *nextElem){ int temp = LocateElem(currentElem); if (temp == -1 || temp == m_iLength - 1) { return false; } else { *nextElem = m_pList[temp + 1]; return true; } } void List::ListTraverse(){ for (int i = 0; i < m_iLength;i++) { cout << m_pList[i]; } } bool List::ListInsert(int i, int *e){ if (i<0 || i>m_iLength) { return false; } for (int k = m_iLength - 1; k >= i; k--) { m_pList[k + 1] = m_pList[k]; } m_pList[i] = *e; m_iLength++; return true; } bool List::ListDelete(int i, int *e){ if (i < 0 || i >= m_iLength) { return false; } *e = m_pList[i]; for (int k = i + 1; k < m_iLength; k++) { m_pList[k-1] = m_pList[k]; } m_iLength--; return true; }
顺序表的优点:在进行遍历和寻址的时候非常快速,效率很高。
缺点:显而易见,当我们想往顺序表中插入一个元素的时候,当前位置向后的所有元素都要向后移动一个位置,这样数据才能顺利地插入进去,删除时同理。那么如何才能避免现象呢?我们需要用到链表。
二、链表的基本操作
我们主要学习单链表,单链表 = 顺序表 + 链表节点,主要操作掌握插入、删除节点。链表节点Node.h
#ifndef NODE_H #define NODE_H class Node{ public: int data; //数据域 Node *next; //指针域 void printNode(); }; #endif
链表节点Node.cpp
#include "Node.h" #include <iostream> using namespace std; void Node::printNode(){ cout << data << endl; }顺序表List.h
#ifndef LIST_H #define LIST_H #include "Node.h" class List{ public: List(); ~List(); void ClearList(); bool ListEmpty(); int ListLength(); bool GetElem(int i,Node *pNode); int LocateElem(Node *pNode); bool PriorElem(Node *pCurrentNode, Node *pPreNode); bool NextElem(Node *pCurrentNode, Node *pNextNode); void ListTraverse(); bool ListInsert(int i, Node *pNode); bool ListDelete(int i, Node *pNode); bool ListInsertHead(Node *pNode); bool ListInsertTail(Node *pNode); private: Node *m_pList; int m_iLength; }; #endif
顺序表List.cpp
#include "List.h" #include <iostream> using namespace std; List::List(){ m_pList = new Node; m_pList->data = 0; m_pList->next = NULL; m_iLength = 0; } bool List::ListEmpty(){ if (m_iLength == 0) { return true; } else { return false; } } int List::ListLength(){ return m_iLength; } void List::ClearList(){ Node *currentNode = m_pList->next; while (currentNode != NULL) { Node *temp = currentNode->next; delete currentNode; currentNode = temp; } m_pList->next = NULL; } 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; m_iLength++; return true; } bool List::ListInsertTail(Node *pNode){ 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; } bool List::ListInsert(int i, Node *pNode){ 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; m_iLength++; return true; } bool List::ListDelete(int i, Node *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; } currentNodeBefore->next = currentNode->next; pNode->data = currentNode->data; delete currentNode; currentNode = NULL; m_iLength--; return true; } bool List::GetElem(int i, Node *pNode){ if (i < 0 || i >= m_iLength) { return false; } Node *currentNode = m_pList; for (int k = 0; k <= i; k++) { currentNode = currentNode->next; } pNode->data = currentNode->data; return true; } int List::LocateElem(Node *pNode){ Node *currentNode = m_pList; int count = 0; while (currentNode->next != 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->next != NULL) { tempNode = currentNode; currentNode = currentNode->next; if (currentNode->data == pCurrentNode->data) { pPreNode->data = tempNode->data; } } return false; } bool List::NextElem(Node *pCurrentNode, Node *pNextNode){ Node *currentNode = m_pList; while (currentNode->next != NULL) { currentNode = currentNode->next; if (currentNode->data == pCurrentNode->data) { if (currentNode->next == NULL) { return false; } pNextNode->data = currentNode->next->data; return true; } } return false; } void List::ListTraverse(){ Node *currentNode = m_pList; while (currentNode->next != NULL) { currentNode = currentNode->next; //头结点的数据域没有意义 currentNode->printNode(); } }测试demo.cpp
#include <stdio.h> #include <stdlib.h> #include <iostream> #include "List.h" using namespace std; int main(void){ Node node1; node1.data = 3; Node node2; node2.data = 4; Node node3; node3.data = 5; Node node4; node4.data = 6; Node node5; node5.data = 7; Node temp; List *pList = new List(); /*pList->ListInsertHead(&node1); pList->ListInsertHead(&node2); pList->ListInsertHead(&node3); pList->ListInsertHead(&node4);*/ pList->ListInsertTail(&node1); pList->ListInsertTail(&node2); pList->ListInsertTail(&node3); pList->ListInsertTail(&node4); pList->ListInsert(1, &node5); //pList->ListDelete(1, &temp); //pList->GetElem(1, &temp); //pList->PriorElem(&node5, &temp); pList->NextElem(&node5, &temp); pList->ListTraverse(); cout << "temp=" << temp.data << endl; delete pList; pList = NULL; system("pause"); return 0; }测试结果:
三、链表的应用之通讯录
通讯录的实现我们可以定义Person类,Person类重载了赋值运算符、比较运算符和输出<<运算符,Person.h#ifndef PERSON_H
#define PERSON_H
#include <string>
#include <ostream>
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); //重载比较运算符
};
#endifPerson.cpp
#include "Person.h" ostream &operator<<(ostream &out, Person &person){ out << person.name << "----" << person.phone << endl; return out; } Person &Person::operator=(Person &person){ this->name = person.name; this->phone = person.phone; return *this; } bool Person::operator==(Person &person){ if (this->name == person.name && this->phone == person.phone) { return true; } return false; }
相关文章推荐
- 数据结构——基本数据结构之链表
- 数据结构与算法——线性表链式存储(单循环链表)
- 【数据结构与算法005】基本数据结构——图
- (摘)面向对象c++数据结构之基本数据结构-链表-使用链表管理器(连载中)
- 【数据结构与算法004】基本数据结构——树
- 数据结构与算法——线性表链式存储(单链表)
- 【数据结构与算法】基本数据结构——队列的链式表示
- 【数据结构与算法002】基本数据结构——栈
- 【数据结构与算法】基本数据结构——队列的顺序表示
- (4) 数据结构与算法 ---- 线性表 及Java实现 顺序表、链表、栈、队列
- 【数据结构与算法】基本数据结构——线性表的链式表示
- 【数据结构与算法】基本数据结构——栈的链式表示
- 郝斌数据结构(1)----数据结构基本分类和链表创建
- 数据结构和算法 (二)数据结构基础、线性表、栈和队列、数组和字符串
- 数据结构之链表基本操作算法演示
- 数据结构实验一--单链表的基本操作的算法
- 【数据结构与算法001】基本数据结构——队列
- 数据结构(一):数据结构的基本概念和算法的时间和空间复杂度
- 数据结构习题分析:已知由一个线性链表表示的线性表中含有三类字符的数据元素,是编写算法将该线性表分割为三个循环链表,其中每个。。。。。
- 再回首,数据结构——线性表、链表上的常见算法