数据结构
包括数据对象和实例,以及构成实例的每个元素之间所存在的各种关系,这种关系可由函数实现。
数据描述
- 公式化描述:所有元素连续存储(如:数组,string);
- 链接描述:每个元素包含下一个元素的地址(如:链表,list);
- 间接寻址:用一张表,收集所有元素的地址;
- 模拟指针:类似链表描述,只是用整数代替指针,此整数包含下一个元素的标志,标志也是整数。
线性表(linear list)
实例形式为:(E1, E2,E3,E4……En)。其中n是有穷自然数,其中Ei是表中的元素,n为表的长度(即元素个数)。如:数组
线性表唯一的关系:优先关系。如:E1优先于E2,E2优先于E3…….
线性表的抽象数据类型描述
线性表 数组
抽象数据类型LinearList{
实例
0或多个元素的有序集合
操作
Create(): 创建一个空线性表
Destroy(): 删除表
IsEmpty(): 如果表为空则返回 t r u e,否则返回false
Length(): 返回表的大小 (即表中元素个数)
Find(k,x): 寻找表中第k 个元素,并把它保存到 x 中;如果不存在,则返回f a l s e
Search(x): 返回元素x在表中的位置;如果x 不在表中,则返回0
Delete(k,x): 删除表中第k 个元素,并把它保存到 x 中;函数返回修改后的线性表
Insert(k,x): 在第k个元素之后插入x;函数返回修改后的线性表
Output(out): 把线性表放入输出流 out 之中
}
#ifndef F_DATA_STRUCT_LINEAR_LIST_ARRAY_20170908_9_44_JHASKDFJHASF_H_
#define F_DATA_STRUCT_LINEAR_LIST_ARRAY_20170908_9_44_JHASKDFJHASF_H_
#ifndef F_DATA_STRUCT_LINEAR_LIST_ARRAY_20170908_9_44_JHASKDFJHASF_H_
#define F_DATA_STRUCT_LINEAR_LIST_ARRAY_20170908_9_44_JHASKDFJHASF_H_
/*
数据结构算法与应用-C++语言描述.pdf
第三章 数据描述
第三节 公式化描述
数据结构:线性表 数组
*/
////////////////////////////////////////////////////////////////////////////
//C++语言实现
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "assert.h"
using namespace std;
const int N_ARRAY_INIT_SIZE = 10; //初始化分配空间的大小
const int N_ARRAY_INCREMENT = 10; //每次分配空间的增量
enum E_Status
{
STATUS_ERROR = -1,
STATUS_SUC = 1
};
template<class T>
void TraceData(const T &pData, int nDataSize)
{
const char *tType= typeid(T).name();
for (int i=0; i<nDataSize; i++)
{
if (0 == strcmp(tType, "int"))
{
TRACE("%d ", pData[i]);
}
else if (0 == strcmp(tType, "float"))
{
TRACE("%f ", pData[i]);
}
}
TRACE("\n");
}
template<class T>
class ListArray
{
public:
ListArray(int nNewSize = 10);
~ListArray();
//! 根据索引, 插入数据
int InsertData(const T &eData, const int nInserIndex);
//! 输出所有数据
void Printf();
//! 根据索引,获取当前数据
bool GetDataByIndex(T &eData, const int nIndex);
//! 根据数据,获取当前数据的索引
bool GetIndexByData(const T &eData, int &nIndex);
//! 获取当前数据个数
int GetCurDataSize();
//! 判断是否为空
bool IsEmpty();
//! 根据索引,删除数据,并将后面的数据前移
bool DeleteDataByIndex(const int nIndex);
//! 排序:直接插入排序算法
bool StraightInsertionSort(T *pData, const int nSize);
//! 排序:选择排序算法
bool SelectionSort(T *pData, const int nSize);
public:
T *m_pElem; //存数据基地址
int m_nCurSize; //当前大小
int m_nTotalSize; //容量
};
template<class T>
ListArray<T>::ListArray(int nNewSize)
:m_nCurSize(0)
,m_nTotalSize(0)
{
if(nNewSize <= 0)
{
return;
}
m_pElem = (T *)malloc(nNewSize * sizeof(T));
if (!m_pElem)
{
return ;
}
m_nCurSize = 0;
m_nTotalSize = nNewSize;
}
template<class T>
ListArray<T>::~ListArray()
{
free(m_pElem);
m_pElem = NULL;
}
//根据索引, 插入数据
template<class T>
int ListArray<T>::InsertData(const T &eData, const int nInserIndex)
{
if ((nInserIndex<0) || (nInserIndex > m_nCurSize))
{
return STATUS_ERROR;
}
//内存空间不够,重新分配新内存
if(m_nTotalSize <= m_nCurSize)
{
T *pNewArray = (T*)realloc(m_pElem, (m_nTotalSize + N_ARRAY_INCREMENT) * sizeof(T));
if (!pNewArray)
{
return STATUS_ERROR;
}
m_pElem = pNewArray;
m_nTotalSize += N_ARRAY_INCREMENT;
}
T *pInsertE = &m_pElem[nInserIndex];
//将插入索引后面的数据后移一个位置
T *pMoveE;
for(pMoveE=&m_pElem[m_nCurSize]; pMoveE>=pInsertE; pMoveE--)
{
int nData = *(pMoveE-1);
*pMoveE = *(pMoveE-1);
}
*pInsertE = eData;
m_nCurSize += 1;
return STATUS_SUC;
}
//输出所有数据
template<class T>
void ListArray<T>::Printf()
{
const char *tType= typeid(T).name();
T eData = 0;
for (int i=0; i<m_nCurSize; i++)
{
eData = m_pElem[i];
cout <<eData;
if (0 == strcmp(tType, "int"))
{
printf("%d /n", eData);
}
else if (0 == strcmp(tType, "float"))
{
printf("%f /n", eData);
}
}
}
//根据索引,获取当前数据
template<class T>
bool ListArray<T>::GetDataByIndex(T &eData, const int nIndex)
{
if((nIndex<0) || (nIndex>=m_nCurSize))
{
return false;
}
eData = m_pElem[nIndex];
return true;
}
//根据数据,获取当前数据的索引
template<class T>
bool ListArray<T>::GetIndexByData(const T &eData, int &nIndex)
{
nIndex = -1;
for(int i=0; i<m_nCurSize; i++)
{
if (m_pElem[i] == eData)
{
nIndex = i;
break;
}
}
return nIndex >= 0 ? true : false;
}
//获取当前数据个数
template<class T>
int ListArray<T>::GetCurDataSize()
{
return m_nCurSize;
}
//判断是否为空
template<class T>
bool ListArray<T>::IsEmpty()
{
return m_nCurSize == 0 ? true : false;
}
//根据索引,删除数据,并将后面的数据前移
template<class T>
bool ListArray<T>::DeleteDataByIndex(const int nIndex)
{
if((nIndex < 0) || (nIndex>=m_nCurSize))
{
return false;
}
for (int i=0; i<m_nCurSize; i++)
{
if (i>=nIndex)
{
m_pElem[i] = m_pElem[i+1];
}
}
m_nCurSize--;
return true;
}
//排序:直接插入排序算法
template<class T>
bool ListArray<T>::StraightInsertionSort(T *pData, const int nSize)
{
if (nSize <= 1)
{
return false;
}
TRACE("排序:直接插入排序算法\n");
T nCurTempDataI(0);
for (int i=1; i<nSize; i++)
{
nCurTempDataI = pData[i];
for (int j=i-1; j>=0; j--)
{
if (nCurTempDataI <= pData[j])
{
pData[j+1] = pData[j+1] + pData[j];
pData[j] = pData[j+1] - pData[j];
pData[j+1] = pData[j+1] - pData[j];
}
}
TraceData(pData, nSize);
}
return true;
}
//排序:选择排序算法
template<class T>
bool ListArray<T>::SelectionSort(T *pData, const int nSize)
{
if (nSize <= 1)
{
return false;
}
TRACE("排序:选择排序算法\n");
int nMinIndex(0);
for(int i=0; i<nSize-1; i++)
{
for(int j=i+1; j<nSize; j++)
{
if (pData[nMinIndex] >= pData[j])
{
nMinIndex = j;
}
}
if (pData[i] != pData[nMinIndex])
{
pData[i] = pData[i] + pData[nMinIndex];
pData[nMinIndex] = pData[i] - pData[nMinIndex];
pData[i] = pData[i] - pData[nMinIndex];
}
TraceData(pData, nSize);
}
return true;
}
void F_Chapter_3_3_Code()
{
ListArray<int> listArray(N_ARRAY_INIT_SIZE);
//根据索引, 插入数据
for (int i=0; i<10; i++)
{
listArray.InsertData(i, 0);
}
/*
listArray.InsertData(22, 5);
listArray.InsertData(88, 5);
*/
//输出所有数据
listArray.Printf();
int nTest = -1;
bool bTest = false;
//根据索引,获取当前数据
bTest = listArray.GetDataByIndex(nTest, listArray.GetCurDataSize()-2);
//根据数据,获取当前数据的索引
bTest = listArray.GetIndexByData(99, nTest);
//判断是否为空
bTest = listArray.IsEmpty();
//根据索引,删除数据,并将后面的数据前移
bTest = listArray.DeleteDataByIndex(2);
//输出所有数据
listArray.Printf();
listArray.InsertData(12, 2);
listArray.InsertData(88, 5);
listArray.InsertData(8, 9);
int *pTemp = (int *)malloc(listArray.m_nCurSize * sizeof(int));
assert(pTemp!=NULL);
memset(pTemp, 0, listArray.m_nCurSize * sizeof(int));
memcpy(pTemp, listArray.m_pElem, listArray.m_nCurSize * sizeof(int));
TRACE("pTemp: Sort before\n");
TraceData(pTemp, listArray.m_nCurSize);
#if 1
//排序:直接插入排序算法
bTest = listArray.StraightInsertionSort(pTemp, listArray.GetCurDataSize());
#endif
#if 1
//排序:选择排序算法
bTest = listArray.SelectionSort(pTemp, listArray.GetCurDataSize());
#endif
TRACE("pTemp: Sort after\n");
TraceData(pTemp, listArray.m_nCurSize);
free(pTemp);
pTemp = NULL;
}
#endif//F_DATA_STRUCT_LINEAR_LIST_ARRAY_20170908_9_44_JHASKDFJHASF_H_
队列
#ifndef F_DATA_STRUCT_QUEUE_20170909_9_15_JHASKDFJHASF_H_
#define F_DATA_STRUCT_QUEUE_20170909_9_15_JHASKDFJHASF_H_
/*
http://blog.csdn.net/juanqinyang/article/details/51354293
队列(queue)是一种采用先进先出(FIFO)策略的抽象数据结构,它的想法来自于生活中排队的策略。
顾客在付款结账的时候,按照到来的先后顺序排队结账,先来的顾客先结账,后来的顾客后结账。
*/
template<class T>
class F_Queue
{
public:
F_Queue(const int nCapacity = 10);
~F_Queue();
bool IsFull(); //判满
bool IsEmpty(); //判空
void CelearQueue(); //清空队列
int QueueSize(); //队列长度
bool EnterQueue(const T & tData); //入队:从队尾增加数据,将队尾索引+1,长度+1
bool DeleteQueue(T & tData); //出队:不删除第一个数据,只是将队头的索引+1
void TraceQueueData();//遍历
public:
T * m_pData;
int m_nCurLen;
int m_nCapacity;
int m_nHead;
int m_nTail;
};
template<class T>
F_Queue<T>::F_Queue(const int nCapacity)
: m_nCapacity(nCapacity)
, m_nCurLen(0)
, m_nHead(0)
, m_nTail(0)
{
if(nCapacity <= 0)
{
return;
}
m_pData = new T[nCapacity * sizeof(T)];
if(!m_pData)
{
exit(1);
}
}
template<class T>
F_Queue<T>::~F_Queue()
{
delete []m_pData;
m_pData = NULL;
}
//判满
template<class T>
bool F_Queue<T>::IsFull()
{
return(m_nCurLen == m_nCapacity);
}
//判空
template<class T>
bool F_Queue<T>::IsEmpty()
{
return(m_nCurLen == 0);
}
//清空队列
template<class T>
void F_Queue<T>::CelearQueue()
{
m_nCurLen = 0;
m_nHead = 0;
m_nTail = 0;
}
//队列长度
template<class T>
int F_Queue<T>::QueueSize()
{
return m_nCurLen;
}
//入队
template<class T>
bool F_Queue<T>::EnterQueue(const T & tData)
{
if(IsFull())
{
return false;
}
m_pData[m_nTail] = tData;
m_nTail++;
m_nTail = m_nTail % m_nCapacity;
m_nCurLen++;
return true;
}
//出队
template<class T>
bool F_Queue<T>::DeleteQueue(T & tData)
{
if(IsEmpty())
{
return false;
}
tData = m_pData[m_nHead];
m_nHead++;
m_nHead = m_nHead % m_nCapacity;
m_nCurLen--;
return true;
}
//遍历
template<class T>
void F_Queue<T>::TraceQueueData()
{
TRACE("\nQueue_Test \n");
for(int i=m_nHead; i<m_nHead+m_nCurLen; i++)
{
TRACE("%d, ", m_pData[i]);
}
TRACE("\n\n");
}
void F_Queue_Test()
{
F_Queue<int> Queue(16);
//入队
Queue.EnterQueue(5);
Queue.EnterQueue(9);
Queue.EnterQueue(12);
Queue.EnterQueue(8);
Queue.EnterQueue(1);
Queue.EnterQueue(9);
Queue.TraceQueueData();
//出队
int nDelTemp = 0;
Queue.DeleteQueue(nDelTemp);
Queue.TraceQueueData();
}
#endif//F_DATA_STRUCT_QUEUE_20170909_9_15_JHASKDFJHASF_H_
队列(链表实现)
#ifndef F_DATA_STRUCTE_QUEUE_LIST_2017_10_10_13_54
#define F_DATA_STRUCTE_QUEUE_LIST_2017_10_10_13_54
/*
数据结构
队列(链表方式实现)
*/
#define SAFE_DELETE(p)\
{\
if (p)\
{\
delete p;\
p = NULL;\
}\
}
template<class T>
struct DataType
{
DataType *pNext;
T tData;
};
template<class T>
class F_QueueList
{
public:
F_QueueList();
~F_QueueList();
//长度
int Lenth();
//判空
bool IsEmpty();
//入队
bool EnterQueue(const T & tData);
//出队
bool DeleteQueue(T & tData);
//打印数据
void TraceData();
private:
DataType<T> *m_pTail;
DataType<T> *m_pHead;
int m_nSize;
};
template<class T>
F_QueueList<T>::F_QueueList()
: m_pHead(NULL)
, m_pTail(NULL)
, m_nSize(0)
{}
template<class T>
F_QueueList<T>::~F_QueueList()
{
DataType<T> *pTemp;
while(m_pHead)
{
pTemp = m_pHead->pNext;
delete m_pHead;
m_pHead = pTemp;
}
}
//长度
template<class T>
int F_QueueList<T>::Lenth()
{
return m_nSize;
}
//判空
template<class T>
bool F_QueueList<T>::IsEmpty()
{
return m_nSize == 0;
}
//入队
template<class T>
bool F_QueueList<T>::EnterQueue(const T & tData)
{
DataType<T> *pNode = new DataType<T>;
if(!pNode)
{
return false;
}
pNode->tData = tData;
pNode->pNext = NULL;
if(0 == m_nSize)
{
m_pHead = pNode;
m_pTail = m_pHead;
}
else
{
m_pTail->pNext = pNode;
m_pTail = pNode;
}
m_nSize++;
return true;
}
//出队
template<class T>
bool F_QueueList<T>::DeleteQueue(T & tData)
{
if(IsEmpty())
{
tData = NULL;
return false;
}
tData = m_pHead->tData;
DataType<T> *pTempNode = m_pHead;
m_pHead = m_pHead->pNext;
SAFE_DELETE(pTempNode);
m_nSize--;
return true;
}
//打印数据
template<class T>
void F_QueueList<T>::TraceData()
{
DataType<T> *pTemp = m_pHead;
while(pTemp)
{
TRACE("%d, ", pTemp->tData);
pTemp = pTemp->pNext;
}
}
void F_QueueList_Test()
{
TRACE("\n队列(链表方式实现) 入队\n");
F_QueueList<int> QueueData;
QueueData.EnterQueue(10);
QueueData.EnterQueue(15);
QueueData.EnterQueue(14);
QueueData.EnterQueue(13);
QueueData.EnterQueue(1);
QueueData.EnterQueue(2);
QueueData.EnterQueue(3);
QueueData.EnterQueue(4);
QueueData.TraceData();
TRACE("\n队列(链表方式实现) 出队\n");
int nData(0);
QueueData.DeleteQueue(nData);
QueueData.DeleteQueue(nData);
QueueData.DeleteQueue(nData);
QueueData.DeleteQueue(nData);
QueueData.DeleteQueue(nData);
QueueData.DeleteQueue(nData);
QueueData.TraceData();
}
#endif//F_DATA_STRUCTE_QUEUE_LIST_2017_10_10_13_54
二叉树
#ifndef F_DATA_STRUCT_BINARY_TREE_20170920_12_20_JHASKDFJHASF_H_
#define F_DATA_STRUCT_BINARY_TREE_20170920_12_20_JHASKDFJHASF_H_
/*
浅谈数据结构-二叉树
二叉树是树的特殊一种,具有如下特点:
1、每个结点最多有两颗子树,结点的度最大为2。
2、左子树和右子树是有顺序的,次序不能颠倒。
3、即使某结点只有一个子树,也要区分左右子树。
满二叉树, 完全二叉树, 非完全二叉树
http://www.cnblogs.com/polly333/p/4740355.html
http://www.cnblogs.com/enjoyall/p/6024657.html
*/
/*
C语言实现
*/
template<class T>
struct BinaryTreeNode_
{
T tData;
BinaryTreeNode_<T> *pLeftTreeNode;
BinaryTreeNode_<T> *pRightTreeNode;
};
//先序遍历二叉树(递归)
template<class T>
void PreOrder(BinaryTreeNode_<T> *pNode)
{
if(pNode)
{
cout << pNode->tData <<", ";
PreOrder(pNode->pLeftTreeNode);
PreOrder(pNode->pRightTreeNode);
}
};
//先序遍历二叉树(递归)
template<class T>
void InOrder(BinaryTreeNode_<T> *pNode)
{
if(pNode)
{
InOrder(pNode->pLeftTreeNode);
cout << pNode->tData <<", ";
InOrder(pNode->pRightTreeNode);
}
};
//后序遍历二叉树(递归)
template<class T>
void AfterOrder(BinaryTreeNode_<T> *pNode)
{
if(pNode)
{
AfterOrder(pNode->pLeftTreeNode);
AfterOrder(pNode->pRightTreeNode);
cout << pNode->tData <<", ";
}
};
//创建二叉树
template<class T>
void CreatBiTree(BinaryTreeNode_<T> *&pNode)
{
BinaryTreeNode_<T>* p = pNode;
T tData;
cin>>tData;
if(tData == -1)
{
pNode = NULL;
}
else
{
pNode = new BinaryTreeNode_<T>();
pNode->tData = tData;
CreatBiTree(pNode->pLeftTreeNode);
CreatBiTree(pNode->pRightTreeNode);
}
}
void F_Binary_Test()
{
BinaryTreeNode_<int> *pRoot = NULL;
//创建二叉树
cout <<"创建二叉树, 以-1结束结点" <<endl;
CreatBiTree(pRoot);
//先序遍历二叉树
cout <<"先序遍历二叉树" <<endl;
PreOrder(pRoot);
}
#endif//F_DATA_STRUCT_BINARY_TREE_20170920_12_20_JHASKDFJHASF_H_
堆栈
#ifndef F_DATA_STRUCT_STACK_20170923_16_15_JHASKDFJHASF_H_
#define F_DATA_STRUCT_STACK_20170923_16_15_JHASKDFJHASF_H_
/*
堆栈(Stack)是一种特殊的线性表。
1. 后进先出( last-in-first-out, LIFO)的数据结构
2. 插入 和 删除 操作都在表的同一端进行。其中一端被称为栈顶(top),另一端被称为栈底(bottom)。
3. 堆栈数据对象的实例 也是 线性表数据对象的实例
4. 栈顶元素存储在element[length-1]中,栈底元素存储在element[0]中
5. 只操作栈顶元素,即后进先出
*/
#if 1
/*
堆栈数据对象的实例 也是 线性表数据对象的实例
因此 堆栈 可以从 ListArrayBase 继承而来
*/
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "assert.h"
using namespace std;
const int N_ARRAY_BASE_INIT_SIZE = 10; //初始化分配空间的大小
const int N_ARRAY_BASE_INCREMENT = 10; //每次分配空间的增量
enum E_StatusBase
{
STATUS_ERROR_BASE = -1,
STATUS_SUC_BASE = 1
};
template<class T>
void TraceDataBase(const T &pData, int nDataSize)
{
for (int i=0; i<nDataSize; i++)
{
TRACE("%d ", pData[i]);
}
TRACE("\n");
}
//线性表的数组类,即为堆栈的基类
template<class T>
class ListArrayBase
{
public:
ListArrayBase(int nNewSize = 10);
~ListArrayBase();
//! 根据索引, 插入数据
int InsertData(const T &eData, const int nInserIndex);
//! 输出所有数据
void Printf();
//! 根据索引,获取当前数据
bool GetDataByIndex(T &eData, const int nIndex);
//! 根据数据,获取当前数据的索引
bool GetIndexByData(const T &eData, int &nIndex);
//! 获取当前数据个数
int GetCurDataSize();
//! 判断是否为空
bool IsEmpty();
//! 根据索引,删除数据,并将后面的数据前移
bool DeleteDataByIndex(const int nIndex);
//! 排序:直接插入排序算法
bool StraightInsertionSort(T *pData, const int nSize);
//! 排序:选择排序算法
bool SelectionSort(T *pData, const int nSize);
//获取数据
T *GetData();
private:
T *m_pElem; //存数据基地址
int m_nCurSize; //当前大小
int m_nTotalSize; //容量
};
template<class T>
ListArrayBase<T>::ListArrayBase(int nNewSize)
:m_nCurSize(0)
,m_nTotalSize(0)
{
if(nNewSize <= 0)
{
return;
}
m_pElem = (T *)malloc(nNewSize * sizeof(T));
if (!m_pElem)
{
return ;
}
m_nCurSize = 0;
m_nTotalSize = nNewSize;
}
template<class T>
ListArrayBase<T>::~ListArrayBase()
{
free(m_pElem);
m_pElem = NULL;
}
//根据索引, 插入数据
template<class T>
int ListArrayBase<T>::InsertData(const T &eData, const int nInserIndex)
{
if ((nInserIndex<0) || (nInserIndex > m_nCurSize))
{
return STATUS_ERROR_BASE;
}
//内存空间不够,重新分配新内存
if(m_nTotalSize <= m_nCurSize)
{
T *pNewArray = (T*)realloc(m_pElem, (m_nTotalSize + N_ARRAY_BASE_INCREMENT) * sizeof(T));
if (!pNewArray)
{
return STATUS_ERROR_BASE;
}
m_pElem = pNewArray;
m_nTotalSize += N_ARRAY_BASE_INCREMENT;
}
T *pInsertE = &m_pElem[nInserIndex];
//将插入索引后面的数据后移一个位置
T *pMoveE;
for(pMoveE=&m_pElem[m_nCurSize]; pMoveE>=pInsertE; pMoveE--)
{
int nData = *(pMoveE-1);
*pMoveE = *(pMoveE-1);
}
*pInsertE = eData;
m_nCurSize += 1;
return STATUS_SUC_BASE;
}
//输出所有数据
template<class T>
void ListArrayBase<T>::Printf()
{
T eData = 0;
for (int i=0; i<m_nCurSize; i++)
{
eData = m_pElem[i];
cout <<eData;
printf("%d /n", eData);
}
}
//根据索引,获取当前数据
template<class T>
bool ListArrayBase<T>::GetDataByIndex(T &eData, const int nIndex)
{
if((nIndex<0) || (nIndex>=m_nCurSize))
{
return false;
}
eData = m_pElem[nIndex];
return true;
}
//根据数据,获取当前数据的索引
template<class T>
bool ListArrayBase<T>::GetIndexByData(const T &eData, int &nIndex)
{
nIndex = -1;
for(int i=0; i<m_nCurSize; i++)
{
if (m_pElem[i] == eData)
{
nIndex = i;
break;
}
}
return nIndex >= 0 ? true : false;
}
//获取当前数据个数
template<class T>
int ListArrayBase<T>::GetCurDataSize()
{
return m_nCurSize;
}
template<class T>
T *ListArrayBase<T>::GetData()
{
if (IsEmpty())
{
return NULL;
}
return m_pElem;
}
//判断是否为空
template<class T>
bool ListArrayBase<T>::IsEmpty()
{
return m_nCurSize == 0 ? true : false;
}
//根据索引,删除数据,并将后面的数据前移
template<class T>
bool ListArrayBase<T>::DeleteDataByIndex(const int nIndex)
{
if((nIndex < 0) || (nIndex>m_nCurSize))
{
return false;
}
for (int i=0; i<m_nCurSize; i++)
{
if (i>=nIndex)
{
m_pElem[i] = m_pElem[i+1];
}
}
m_nCurSize--;
return true;
}
//排序:直接插入排序算法
template<class T>
bool ListArrayBase<T>::StraightInsertionSort(T *pData, const int nSize)
{
if (nSize <= 1)
{
return false;
}
TRACE("排序:直接插入排序算法\n");
T nCurTempDataI(0);
for (int i=1; i<nSize; i++)
{
nCurTempDataI = pData[i];
for (int j=i-1; j>=0; j--)
{
if (nCurTempDataI <= pData[j])
{
pData[j+1] = pData[j+1] + pData[j];
pData[j] = pData[j+1] - pData[j];
pData[j+1] = pData[j+1] - pData[j];
}
}
TraceDataBase(pData, nSize);
}
return true;
}
//排序:选择排序算法
template<class T>
bool ListArrayBase<T>::SelectionSort(T *pData, const int nSize)
{
if (nSize <= 1)
{
return false;
}
TRACE("排序:选择排序算法\n");
int nMinIndex(0);
for(int i=0; i<nSize-1; i++)
{
for(int j=i+1; j<nSize; j++)
{
if (pData[nMinIndex] >= pData[j])
{
nMinIndex = j;
}
}
if (pData[i] != pData[nMinIndex])
{
pData[i] = pData[i] + pData[nMinIndex];
pData[nMinIndex] = pData[i] - pData[nMinIndex];
pData[i] = pData[i] - pData[nMinIndex];
}
TraceDataBase(pData, nSize);
}
return true;
}
template<class T>
class F_DataStructeStack : private ListArrayBase<T>
{
public:
F_DataStructeStack(const int nMaxSize)
:ListArrayBase(nMaxSize)
{}
//获取栈数据
T GetTopData()
{
if (ListArrayBase::IsEmpty())
{
return NULL;
}
return m_pElem[m_nCurSize-1];
}
//! 判断是否为空
bool IsEmpty()
{
return ListArrayBase::IsEmpty();
}
//获取数据
T* GetData()
{
return ListArrayBase::GetData();
}
//! 获取当前数据个数
int GetCurDataSize()
{
return ListArrayBase::GetCurDataSize();
}
//增加数据
F_DataStructeStack<T> &AddData(const T tData)
{
ListArrayBase::InsertData(tData, GetCurDataSize());
return *this;
}
//删除数据
F_DataStructeStack<T> &DeleteData()
{
ListArrayBase::DeleteDataByIndex(GetCurDataSize());
return *this;
}
};
void F_DataStructeStack_Test()
{
F_DataStructeStack<int> pData(N_ARRAY_BASE_INIT_SIZE);
bool bEmpty = pData.IsEmpty();
for (int i=0; i<10; i++)
{
pData.AddData(i*2);
}
pData.AddData(88);
for (int i=0; i<10; i++)
{
pData.AddData(i*2);
}
TRACE("\DataStructe: Stack, AddData after\n");
TraceDataBase(pData.GetData(), pData.GetCurDataSize());
pData.DeleteData();
TRACE("\DataStructe: Stack, DeleteData after\n");
TraceDataBase(pData.GetData(), pData.GetCurDataSize());
bEmpty = pData.IsEmpty();
}
#endif
#endif//F_DATA_STRUCT_STACK_20170923_16_15_JHASKDFJHASF_H_
链表描述
#ifndef F_DATA_STRUCT_LIST_CHAIN_20170927_13_51_JHASKDFJHASF_H_
#define F_DATA_STRUCT_LIST_CHAIN_20170927_13_51_JHASKDFJHASF_H_
/*
链表描述
类ChainNode 和ListChain
在链表描述中,数据对象实例的每个元素都放在单元或节点中进行描述。
不过,节点不必是一个数组元素,因此没有什么公式可用来定位某个元素。
取而代之的是,每个节点中都包含了与该节点相关的其他节点的位置信息
*/
#if 1
template <class T>
class ChainNode
{
public:
T tData;
ChainNode<T> *pNextLink;
};
template<class T>
class ListChain
{
public :
ListChain();
~ListChain();
//链表是否为空
bool IsEmpty() const;
//链表长度
int Length() const;
//根据 索引 查找 数据
bool FindDataByIndex(int nIndex, T& tData) const;
//根据 数据 查找 索引
int SearchIndexByData(const T& tData) const;
//根据 索引 删除 数据
ListChain<T>& DeleteDataByIndex(int nIndex, T& tData);
//根据 索引 插入 数据
ListChain<T>& InsertDataByIndex(int nIndex, const T& tData);
//在链表尾部增加数据
ListChain<T>& PushBack(const T& tData);
//打印数据
void TraceData();
public:
ChainNode<T> *m_pFirstNode; // 指向第一个节点的指针
};
template<class T>
ListChain<T>::ListChain()
:m_pFirstNode(0)
{}
template<class T>
ListChain<T>::~ListChain()
{
ChainNode<T> *pTempFirstNode;
while (m_pFirstNode)
{
pTempFirstNode = m_pFirstNode->pNextLink;
delete m_pFirstNode;
m_pFirstNode = pTempFirstNode;
}
}
//链表是否为空
template<class T>
bool ListChain<T>::IsEmpty() const
{
return m_pFirstNode == 0;
}
//链表长度
template<class T>
int ListChain<T>::Length() const
{
int nSize(0);
ChainNode<T> *pCurNode = m_pFirstNode;
while (pCurNode)
{
nSize++;
pCurNode = pCurNode->pNextLink;
}
return nSize;
}
//根据 索引 查找 数据
template<class T>
bool ListChain<T>::FindDataByIndex(int nIndex, T& tData) const
{
if(IsEmpty() || nIndex <1)
{
return false;
}
int nCurIndex(1);
ChainNode<T> *pCurNode = m_pFirstNode;
while((nCurIndex <= nIndex) && pCurNode)
{
pCurNode = pCurNode->pNextLink;
nCurIndex++;
}
if(pCurNode)
{
tData = pCurNode->tData;
}
return true;
}
//根据 数据 查找 索引
template<class T>
int ListChain<T>::SearchIndexByData(const T& tData) const
{
int nIndex(-1);
ChainNode<T> *pCurNode = m_pFirstNode;
while (pCurNode)
{
nIndex++;
if (tData == pCurNode->tData)
{
return nIndex;
}
pCurNode = pCurNode->pNextLink;
}
return -1;
}
//根据 索引 插入 数据
template<class T>
ListChain<T>& ListChain<T>::InsertDataByIndex(int nIndex, const T& tData)
{
if(nIndex < 0)
{
return *this;
}
ChainNode<T> *pNode = m_pFirstNode;
ChainNode<T> *pNewNode = new ChainNode<T>;
if(!pNewNode)
{
return *this;
}
pNewNode->tData = tData;
//从开始位置插入元素
if (0 == nIndex)
{
pNewNode->pNextLink = pNode;
m_pFirstNode = pNewNode;
}
else
{
//找到插入数据的节点位置
int nCurIndex(1);
while(pNode && (nCurIndex < nIndex))
{
pNode = pNode->pNextLink;
nCurIndex++;
}
pNewNode->pNextLink = pNode->pNextLink;
pNode->pNextLink = pNewNode;
}
return *this;
}
//在链表尾部增加数据
template<class T>
ListChain<T>& ListChain<T>::PushBack(const T& tData)
{
ChainNode<T> *pNodeNew = new ChainNode<T>;
if (!pNodeNew)
{
return *this;
}
int nEndIndex(0);
//找到末尾位置的索引
if(m_pFirstNode)
{
ChainNode<T> *pNode = m_pFirstNode;
while(pNode)
{
pNode = pNode->pNextLink;
nEndIndex++;
}
}
//从末尾位置的索引插入数据
InsertDataByIndex(nEndIndex, tData);
return *this;
}
//打印数据
template<class T>
void ListChain<T>::TraceData()
{
TRACE("\n单向链表数据打印\n");
ChainNode<T> *pNode = m_pFirstNode;
while(pNode)
{
TRACE("%d, ", pNode->tData);
pNode = pNode->pNextLink;
}
}
//根据 索引 删除 数据
template<class T>
ListChain<T>& ListChain<T>::DeleteDataByIndex(int nIndex, T& tData)
{
if (nIndex<0 || !m_pFirstNode)
{
return *this;
}
ChainNode<T> *pCurNode = m_pFirstNode;
if(0 == nIndex)
{
tData = m_pFirstNode->tData;
m_pFirstNode = m_pFirstNode->pNextLink;
delete pCurNode;
pCurNode = NULL;
}
else
{
//找到删除数据的上一个节点位置
int nCurIndex(1);
while(pCurNode && (nCurIndex < nIndex))
{
pCurNode = pCurNode->pNextLink;
nCurIndex++;
}
ChainNode<T> *pDeleteNode;
pDeleteNode = pCurNode->pNextLink;
pCurNode->pNextLink = pDeleteNode->pNextLink;
delete pDeleteNode;
pDeleteNode = NULL;
}
return *this;
}
//链表描述
void F_DataStructeListChain_Test()
{
ListChain<int> listChain;
//从头部插入数据
listChain.InsertDataByIndex(0, 9);
listChain.InsertDataByIndex(0, 8);
listChain.InsertDataByIndex(0, 5);
listChain.InsertDataByIndex(0, 6);
listChain.InsertDataByIndex(0, 7);
listChain.TraceData();
//从中部插入数据
listChain.InsertDataByIndex(2, 22);
listChain.TraceData();
//从尾部插入
listChain.PushBack(10);
listChain.PushBack(14);
listChain.PushBack(11);
listChain.TraceData();
//查找索引
int nTemp = listChain.SearchIndexByData(7);
//查找数据
int nDtata(0);
listChain.FindDataByIndex(10, nDtata);
//将头部数据删除
listChain.DeleteDataByIndex(0, nDtata);
listChain.TraceData();
//将中部数据删除
listChain.DeleteDataByIndex(3, nDtata);
listChain.TraceData();
listChain.DeleteDataByIndex(5, nDtata);
listChain.TraceData();
//将尾部数据删除
listChain.DeleteDataByIndex(listChain.Length()-1, nDtata);
listChain.TraceData();
}
#endif
#endif//F_DATA_STRUCT_LIST_CHAIN_20170927_13_51_JHASKDFJHASF_H_