当前位置:   article > 正文

C++常用数据结构_c++数据结构

c++数据结构

                                                                                  常用数据结构


1.线性表

定义:

  • 由n个具有相同性质的数据元素组成的有穷序列

特点:

(一对一的关系)

  • 存在唯一一个称为”第一个“的数据元素,它没有直接的前驱。
  • 存在唯一一个称为“最后一个”的元素,他没有直接后驱。
  • 除第一个数据元素以外,表中的每个数据元素有且仅有一个直接前驱
  • 除第一个数据元素以外,表中的每个数据元素有且仅有一个直接后驱

​1.1顺序表

定义:

  • 用一组地址连续存储单元依次存储线性表中每个数据元素。

特点:

  •  逻辑关系相邻的两个元素在物理位置上也相邻。

Image result for 顺序表

实现:

  • c语言实现:
  1. typedef struct {
  2. int items[LISTSIZE];
  3. int length;
  4. } SqList;
  • length:线性表当前的长度。
  • LISTSIZE:最大容量。
  • c++实现:
  1. template <typename T>
  2. class sqlist{
  3. public:
  4. sqlist(int maxsize=10):Maxsize(maxsize)
  5. {
  6. elements=new T[maxsize];
  7. length=0;
  8. }
  9. private:
  10. int Maxsize;//最大容量
  11. T *elements;//元素初始地址
  12. int length;//当前有效长度
  13. };

基本操作:

  • 初始化顺序表

  1. //初始化顺序表,表的长度设置为0
  2. void InitList(SqList *L)
  3. {
  4. L->length=0;
  5. }
  • 求顺序表中当前元素的个数

  1. //顺序表的长度
  2. int ListLength(SqList * L)
  3. {
  4. return L->length;
  5. }
  • 判断顺序表是否为空

  1. //判断顺序表是否为空
  2. bool ListEmpty(SqList *L)
  3. {
  4. if(L->length==0)
  5. return true;
  6. else
  7. return false;
  8. }
  • 向顺序表中插入数据元素

  1. //向顺序表中插入数据元素
  2. bool ListInsert(SqList *L,int pos,int item)
  3. {
  4. int i;
  5. if(L->length==LISTSIZE)
  6. {
  7. printf("顺序列表已满,无法进行插入操作");
  8. return false;
  9. }
  10. if(pos<1||pos>L->length+1)
  11. {
  12. printf("插入位置不合法");
  13. return false;
  14. }
  15. for(i=L->length-1;i>=pos-1;i--)
  16. {
  17. L->items[i+1]=L->items[i];
  18. }
  19. L->items[pos-1]=item;
  20. L->length++;
  21. return true;
  22. }
  • 删除顺序表中的元素

  1. //删除顺序表中的元素
  2. bool ListDelete(SqList *L,int pos,int *item)
  3. {
  4. int i;
  5. if(L->length==0)
  6. {
  7. printf("顺序表为空表");
  8. return false;
  9. }
  10. if(pos<1||pos>L->length)
  11. {
  12. printf("删除位置无效");
  13. }
  14. *item=L->items[pos-1];
  15. for(int i=pos-1;i<L->length-1;i++)
  16. {
  17. L->items[i]=L->items[i+1];
  18. }
  19. L->length--;
  20. return true;
  21. }
  • 查找指定元素在顺序表中的位置

  1. //查找制定元素在顺序表中的位置
  2. int Find(SqList L,int item)
  3. {
  4. int pos=0;
  5. if(ListEmpty(&L))
  6. {
  7. printf("顺序表为空表,无法进行查找操作");
  8. return 0;
  9. }
  10. while(pos<L.length&&L.items[pos]!=item)
  11. {
  12. pos++;
  13. }
  14. if(pos<L.length)
  15. return pos+1;
  16. else
  17. return 0;
  18. }
  • 获取顺序表中指定位置上的数据元素

  1. //获得顺序表中指定位置上的数据元素
  2. int GetElem(SqList *L,int pos,int *item)
  3. {
  4. if(ListEmpty(L))
  5. return 0;
  6. if(pos<1||pos>L->length)
  7. return 0;
  8. *item=L->items[pos-1];
  9. return 1;
  10. }
  • 遍历顺序表
  1. //遍历顺序表
  2. void TravereList(SqList *L)
  3. {
  4. int pos =0;
  5. while(pos<L->length)
  6. {
  7. printf("item1: %d",L->items[pos]);
  8. pos++;
  9. }
  10. }

c语言版本: 

  1. #include <iostream>
  2. using namespace std;
  3. #define LISTSIZE 100
  4. typedef struct {
  5. int items[LISTSIZE];
  6. int length;
  7. } SqList;
  8. //初始化顺序表,表的长度设置为0
  9. void InitList(SqList *L)
  10. {
  11. L->length=0;
  12. }
  13. //顺序表的长度
  14. int ListLength(SqList * L)
  15. {
  16. return L->length;
  17. }
  18. //判断顺序表是否为空
  19. bool ListEmpty(SqList *L)
  20. {
  21. if(L->length==0)
  22. return true;
  23. else
  24. return false;
  25. }
  26. //向顺序表中插入数据元素
  27. bool ListInsert(SqList *L,int pos,int item)
  28. {
  29. int i;
  30. if(L->length==LISTSIZE)
  31. {
  32. printf("顺序列表已满,无法进行插入操作");
  33. return false;
  34. }
  35. if(pos<1||pos>L->length+1)
  36. {
  37. printf("插入位置不合法");
  38. return false;
  39. }
  40. for(i=L->length-1;i>=pos-1;i--)
  41. {
  42. L->items[i+1]=L->items[i];
  43. }
  44. L->items[pos-1]=item;
  45. L->length++;
  46. return true;
  47. }
  48. //删除顺序表中的元素
  49. bool ListDelete(SqList *L,int pos,int *item)
  50. {
  51. int i;
  52. if(L->length==0)
  53. {
  54. printf("顺序表为空表");
  55. return false;
  56. }
  57. if(pos<1||pos>L->length)
  58. {
  59. printf("删除位置无效");
  60. }
  61. *item=L->items[pos-1];
  62. for(int i=pos-1;i<L->length-1;i++)
  63. {
  64. L->items[i]=L->items[i+1];
  65. }
  66. L->length--;
  67. return true;
  68. }
  69. //查找制定元素在顺序表中的位置
  70. int Find(SqList L,int item)
  71. {
  72. int pos=0;
  73. if(ListEmpty(&L))
  74. {
  75. printf("顺序表为空表,无法进行查找操作");
  76. return 0;
  77. }
  78. while(pos<L.length&&L.items[pos]!=item)
  79. {
  80. pos++;
  81. }
  82. if(pos<L.length)
  83. return pos+1;
  84. else
  85. return 0;
  86. }
  87. //获得顺序表中指定位置上的数据元素
  88. int GetElem(SqList *L,int pos,int *item)
  89. {
  90. if(ListEmpty(L))
  91. return 0;
  92. if(pos<1||pos>L->length)
  93. return 0;
  94. *item=L->items[pos-1];
  95. return 1;
  96. }
  97. //遍历顺序表
  98. void TravereList(SqList *L)
  99. {
  100. int pos =0;
  101. while(pos<L->length)
  102. {
  103. printf("item1: %d",L->items[pos]);
  104. pos++;
  105. }
  106. }
  107. int main()
  108. {
  109. SqList Fibonacci;
  110. cout<<"建立顺序表"<<endl;
  111. InitList(&Fibonacci);
  112. for(int i=0;i<7;)
  113. {
  114. int num;
  115. cin>>num;
  116. if(ListInsert(&Fibonacci,i+1,num))
  117. i++;
  118. }
  119. TravereList(&Fibonacci);
  120. int item;
  121. ListDelete(&Fibonacci,7,&item);
  122. TravereList(&Fibonacci);
  123. return 0;
  124. }

c++版本:

  1. #include<iostream>
  2. using namespace std;
  3. template <typename T>
  4. class sqlist{
  5. public:
  6. sqlist(int maxsize=10):Maxsize(maxsize)
  7. {
  8. elements=new T[maxsize];
  9. length=0;
  10. }
  11. //打印顺序表的长度
  12. int listLength()
  13. {
  14. return length;
  15. }
  16. //判断顺序表是否为空
  17. bool IsEmpty()
  18. {
  19. return length==0;
  20. }
  21. //顺序表中插入元素
  22. void InsertElement(T elem,int position)
  23. {
  24. if(IsEmpty())
  25. {
  26. elements[length++]=elem;
  27. }
  28. else
  29. {
  30. for(int i=length;i>=position;i--)
  31. elements[i]=elements[i-1];
  32. elements[position-1]=elem;
  33. length++;
  34. }
  35. }
  36. //顺序表中删除元素
  37. void DelElement(T elem,int position)
  38. {
  39. T del_elem=elements[position-1];
  40. for(int i=position-1;i<length-1;i++)
  41. elements[i]=elements[i+1];
  42. length--;
  43. }
  44. //查找元素的位置
  45. int FindElement(T elem)
  46. {
  47. int i;
  48. for(i=0;i<length;i++)
  49. {
  50. if(elements[i]==elem)
  51. {
  52. std::cout<<"i: "<<i<<std::endl;
  53. break;
  54. }
  55. }
  56. if(i==length)
  57. {
  58. std::cout<<"find not"<<std::endl;
  59. return -1;
  60. }
  61. else
  62. {
  63. std::cout<<"find yes"<<std::endl;
  64. return i;
  65. }
  66. }
  67. //打印
  68. void Printf()
  69. {
  70. for(int i=0;i<length;i++)
  71. std::cout<<elements[i]<<" ";
  72. std::cout<<std::endl;
  73. }
  74. private:
  75. int Maxsize;//最大容量
  76. T *elements;//元素初始地址
  77. int length;//当前有效长度
  78. };
  79. int main()
  80. {
  81. sqlist<int> sq(20);
  82. sq.InsertElement(10,2);
  83. sq.Printf();
  84. sq.InsertElement(30,1);
  85. sq.Printf();
  86. sq.InsertElement(50,1);
  87. sq.Printf();
  88. sq.InsertElement(100,2);
  89. sq.Printf();
  90. sq.DelElement(30,3);
  91. sq.Printf();
  92. sq.FindElement(100);
  93. return 0;
  94. }

1.2链表 

定义:

  • 用一组任意存储单元存储线性表中的数据元素。

特点:

  • 相比顺序存储结构,链式存储结构中,除了需要存储数据元素信息之外,还需要存储它的后继元素的存储地址(指针)
  • 单链表结点的物理位置不一定连续,单链表逻辑上通过指针实现连续。
  • 单链表有一个头结点和一个尾结点,并且只有尾结点没有后继结点,其他结点有且仅有一个后继结点。
  • 只要知道了链表的头结点,就可以遍历整个链表。
     

  • 单链表的每一个结点包含两部分:数据域和指针域。
  • 表头:用来存放第一个结点的地址。
  • 表尾:表尾没有后继,所以尾结点的指针域为空指针(NULL)。

 实现:

  • c语言定义:
  1. typedef struct node{
  2. int data;//数据域
  3. node * next;//指针域
  4. }LNode,*LinkList;//LinkList是指向LNode类型数据的指针类型定义
  • LinkList是指向LNode类型数据的指针类型定义 ,也就是说,在定义一个指向LNode类型数据的指针变量时,语句
LNode *L;

LinkList L;

是等价的。

  • c++定义:
  1. class ListNode{
  2. public:
  3. ListNode * next;
  4. int data;
  5. };
  6. class LinkList
  7. {
  8. public:
  9. LinkList()
  10. {
  11. node=new ListNode;
  12. node->next=NULL;
  13. }
  14. ~LinkList()
  15. {
  16. delete node;
  17. }
  18. void CreateLinkListBack(int n);
  19. void CreateLinkListHead(int n);
  20. void InsertNode(int position,int elem);
  21. void removeNode(ListNode* p);
  22. ListNode* findNode(int value);
  23. void PrintLinkList();
  24. public:
  25. ListNode *node;
  26. };

基本操作:

  • 初始化链表
  1. //初始化链表
  2. LinkList init_list()
  3. {
  4. LinkList L=new LNode;
  5. if(!L)
  6. return NULL;
  7. L->next=NULL;//指针域置空
  8. return L;
  9. }
  • 打印链表
  1. //打印链表
  2. void Printf_list(LinkList &L)
  3. {
  4. LinkList temp=L->next;
  5. while(temp!=NULL)
  6. {
  7. cout<<temp->data<<"->";
  8. temp=temp->next;
  9. }
  10. }
  •  插入数据(头插)

步骤:

  1. 先创建一个新节点s(LinkList),并给数据域赋值,
  2. 新节点的指针域指向L-next,
  3. L的指针域next指向s。

  1. //插入数据(头插)
  2. void create_LinkList(LinkList &L,int n)
  3. {
  4. while(n--)
  5. {
  6. LinkList s=new LNode;
  7. cin>>s->data;
  8. s->next=L->next;
  9. L->next=s;
  10. }
  11. }

 

注意:使用头插法插入数据后,链表中数据的顺序和插入前的数据顺序相反。 

  • 插入数据(尾插)

步骤:

  1. 先让r节点指向尾结点,
  2. 创建一个新节点s(LinkList),并给数据域赋值,且s->next为NULL,因为s为尾结点,
  3. r的指针域指向s,
  4. 更新尾节点,即r=s。

  1. //插入数据(尾插)
  2. void create_LinkList_back(LinkList &L,int n)
  3. {
  4. LinkList r=L;
  5. while(n--)
  6. {
  7. LinkList s=new LNode;
  8. cin>>s->data;
  9. s->next=NULL;
  10. r->next=s;
  11. r=s;
  12. }
  13. }

 注意:使用尾插法插入数据后,链表中数据的顺序和插入前的数据顺序相同。 

  • 在指定位置插入数据
  1. //插入数据
  2. void InsertList(LinkList q,int e)
  3. {
  4. LinkList p=new LNode;
  5. p->data=e;
  6. p->next=q->next;
  7. q->next=p;
  8. }

 

  • 查找相应数据
  1. LinkList Get_elem(LinkList &L,int e)
  2. {
  3. LinkList temp=L->next;
  4. while(temp!=NULL)
  5. {
  6. if(e==temp->data)
  7. {
  8. return temp;
  9. }
  10. temp=temp->next;
  11. }
  12. return NULL;
  13. }

完整程序

  1. #include<iostream>
  2. using namespace std;
  3. typedef struct node{
  4. int data;//数据域
  5. struct node * next;//指针域
  6. }LNode,*LinkList;//LinkList是指向LNode类型数据的指针类型定义
  7. //初始化链表
  8. LinkList init_list()//引用
  9. {
  10. LinkList L=new LNode;
  11. if(!L)
  12. return NULL;
  13. L->next=NULL;//指针域置空
  14. return L;
  15. }
  16. //插入数据(头插)
  17. void create_LinkList(LinkList &L,int n)
  18. {
  19. while(n--)
  20. {
  21. LinkList s=new LNode;
  22. cin>>s->data;
  23. s->next=L->next;
  24. L->next=s;
  25. }
  26. }
  27. //插入数据(尾插)
  28. void create_LinkList_back(LinkList &L,int n)
  29. {
  30. LinkList r=L;
  31. while(n--)
  32. {
  33. LinkList s=new LNode;
  34. cin>>s->data;
  35. s->next=NULL;
  36. r->next=s;
  37. r=s;
  38. }
  39. }
  40. //打印链表
  41. void Printf_list(LinkList &L)
  42. {
  43. LinkList temp=L->next;
  44. while(temp!=NULL)
  45. {
  46. cout<<temp->data<<"->";
  47. temp=temp->next;
  48. }
  49. cout<<endl;
  50. }
  51. //插入数据
  52. void InsertList(LinkList q,int e)
  53. {
  54. LinkList p=new LNode;
  55. p->data=e;
  56. p->next=q->next;
  57. q->next=p;
  58. }
  59. LinkList Get_elem(LinkList &L,int e)
  60. {
  61. LinkList temp=L->next;
  62. while(temp!=NULL)
  63. {
  64. if(e==temp->data)
  65. {
  66. return temp;
  67. }
  68. temp=temp->next;
  69. }
  70. return NULL;
  71. }
  72. int main()
  73. {
  74. LinkList L=init_list();
  75. if(!L)
  76. {
  77. cout<<"初始化失败"<<endl;
  78. return 0;
  79. }
  80. cout<<"初始化成功"<<endl;
  81. int num;
  82. cout<<"请输入插入的数量:"<<endl;
  83. cin>>num;
  84. create_LinkList_back(L,num);
  85. Printf_list(L);
  86. int elem;
  87. LinkList elem_list;
  88. cout<<"请输入需要查找的数"<<endl;
  89. cin>>elem;
  90. elem_list=Get_elem(L,elem);
  91. while(!elem_list)
  92. {
  93. cout<<"没有查找到,请重新输入"<<endl;
  94. cin>>elem;
  95. elem_list=Get_elem(L,elem);
  96. }
  97. cout<<"找到相应数据,数据地址为:"<<elem_list<<endl;
  98. if(elem_list!=NULL)
  99. {
  100. cout<<"请输入需要插入的数"<<endl;
  101. int elem_insert;
  102. cin>>elem_insert;
  103. InsertList(elem_list,elem_insert);
  104. Printf_list(L);
  105. }
  106. return 0;
  107. }

c++版本:

  1. #include <iostream>
  2. using namespace std;
  3. class ListNode{
  4. public:
  5. ListNode * next;
  6. int data;
  7. };
  8. class LinkList
  9. {
  10. public:
  11. LinkList()
  12. {
  13. node=new ListNode;
  14. node->next=NULL;
  15. }
  16. ~LinkList()
  17. {
  18. delete node;
  19. }
  20. void CreateLinkListBack(int n);
  21. void CreateLinkListHead(int n);
  22. void InsertNode(int position,int elem);
  23. void removeNode(ListNode* p);
  24. ListNode* findNode(int value);
  25. void PrintLinkList();
  26. public:
  27. ListNode *node;
  28. };
  29. //头插
  30. void LinkList::CreateLinkListHead(int n)
  31. {
  32. while(n--)
  33. {
  34. //插入的数据
  35. ListNode* l=new ListNode;
  36. cin>>l->data;
  37. l->next=node->next;
  38. node->next=l;
  39. }
  40. }
  41. //尾插
  42. void LinkList::CreateLinkListBack(int n)
  43. {
  44. ListNode* r=node;
  45. while(n--)
  46. {
  47. ListNode* l=new ListNode;
  48. cin>>l->data;
  49. l->next=NULL;
  50. r->next=l;
  51. r=l;
  52. }
  53. }
  54. //在第i个位置插入元素
  55. void LinkList::InsertNode(int position,int elem)
  56. {
  57. int j;
  58. ListNode* p=node->next;
  59. for(j=1;j<position-1;j++)
  60. {
  61. p=p->next;
  62. if(p==NULL)
  63. break;
  64. }
  65. if(p==NULL &&j<(position-1))
  66. return ;
  67. // while(p)
  68. // {
  69. // j++;
  70. // if(j==position)
  71. // break;
  72. // p=p->next;
  73. // }
  74. ListNode* q=new ListNode;
  75. q->data=elem;
  76. q->next=p->next;
  77. p->next=q;
  78. }
  79. //移除节点
  80. void LinkList::removeNode(ListNode* p)
  81. {
  82. if(p==NULL)
  83. return;
  84. ListNode* temp=node;
  85. while(temp->next!=p)
  86. {
  87. temp=temp->next;
  88. }
  89. temp->next=p->next;
  90. delete p;
  91. }
  92. //寻找某节点
  93. ListNode* LinkList::findNode(int value)
  94. {
  95. ListNode* temp=node->next;
  96. while(temp)
  97. {
  98. if(temp->data==value)
  99. return temp;
  100. temp=temp->next;
  101. }
  102. return NULL;
  103. }
  104. //打印链表
  105. void LinkList::PrintLinkList()
  106. {
  107. ListNode* temp=node->next;
  108. while(temp)
  109. {
  110. cout<<temp->data<<"->";
  111. temp=temp->next;
  112. }
  113. std::cout<<std::endl;
  114. }
  115. int main()
  116. {
  117. LinkList list;
  118. list.CreateLinkListHead(5);
  119. list.PrintLinkList();
  120. list.InsertNode(4,9);
  121. list.PrintLinkList();
  122. ListNode* address=list.findNode(2);
  123. list.removeNode(address);
  124. list.PrintLinkList();
  125. return 0;
  126. }

2.栈

  • 定义:

栈(stack)是一种元素满足后进先出(Last in first out, LIFO)规则的线性表

  • 特点:

  • 栈的本质是一种线性表, 但是具有其特殊的操作要求——元素后进先出。这种要求也决定了栈的操作是在表尾进行
  • 栈底(bottom):栈的表头
  • 栈顶(top):将栈的表尾,所以栈的所有操作都是在栈顶进行的。
  • 添加元素,称为入栈(push);删除元素,称为出栈(pop)。
  • 实现:

栈可以用顺序存储实现,也可以用链式存储实现,分别成为顺序栈和链栈。但一般使用顺序存储实现,因为栈不允许在栈中间进行插入和删除,需要准寻栈特有的规则。

  • 动态实现 
  1. typedef struct SqStack_dynamic{
  2. int* base;//栈底
  3. int* top;//栈顶
  4. }SqStack_dynamic;
  • 静态实现
  1. typedef struct SqStack_static{
  2. int data[Maxsize];
  3. int top;//栈顶
  4. }SqStack_static;
  • C++
  1. class stack_static{
  2. public:
  3. stack_static()
  4. {
  5. MaxSize=10;
  6. top=0;
  7. data= new int[MaxSize];
  8. }
  9. void push(int e);
  10. void pop(int &e);
  11. void GetTop(int &e);
  12. private:
  13. int MaxSize;
  14. int top;
  15. int *data;
  16. };

 操作: 

  • 初始化
  1. void InitStack(SqStack_dynamic &stack)
  2. {
  3. stack.base= new int[Maxsize];
  4. stack.top=stack.base;
  5. }
  • 入栈
  1. void push(SqStack_dynamic &stack,int e)
  2. {
  3. if((stack.top-stack.base)>=Maxsize)
  4. return;
  5. *stack.top=e;
  6. stack.top++;
  7. }
  1. void stack_static::push(int e)
  2. {
  3. data[top]=e;
  4. top++;
  5. }
  • 出栈
  1. void pop(SqStack_dynamic &stack,int &e)
  2. {
  3. if(stack.base==stack.top)
  4. return;
  5. stack.top--;
  6. e=*stack.top;
  7. }
  1. void stack_static::pop(int &e)
  2. {
  3. top--;
  4. e=data[top];
  5. }
  •  栈顶元素
  1. int GetTop(SqStack_dynamic &stack)
  2. {
  3. if(stack.base!=stack.top)
  4. return *(stack.top-1);
  5. else
  6. return -1;
  7. }
  1. void stack_static::GetTop(int &e)
  2. {
  3. if(top!=MaxSize)
  4. e=data[top-1];
  5. else
  6. e=-1;
  7. }

 完整程序

  1. #include<iostream>
  2. using namespace std;
  3. #define Maxsize 100
  4. typedef struct SqStack_dynamic{
  5. int* base;//栈底
  6. int* top;//栈顶
  7. }SqStack_dynamic;
  8. class stack_static{
  9. public:
  10. stack_static()
  11. {
  12. MaxSize=10;
  13. top=0;
  14. data= new int[MaxSize];
  15. }
  16. void push(int e);
  17. void pop(int &e);
  18. void GetTop(int &e);
  19. private:
  20. int MaxSize;
  21. int top;
  22. int *data;
  23. };
  24. void stack_static::push(int e)
  25. {
  26. data[top]=e;
  27. top++;
  28. }
  29. void stack_static::pop(int &e)
  30. {
  31. top--;
  32. e=data[top];
  33. }
  34. void stack_static::GetTop(int &e)
  35. {
  36. if(top!=MaxSize)
  37. e=data[top-1];
  38. else
  39. e=-1;
  40. }
  41. void InitStack(SqStack_dynamic &stack)
  42. {
  43. stack.base= new int[Maxsize];
  44. stack.top=stack.base;
  45. }
  46. void push(SqStack_dynamic &stack,int e)
  47. {
  48. if((stack.top-stack.base)>=Maxsize)
  49. return;
  50. *stack.top=e;
  51. stack.top++;
  52. }
  53. void pop(SqStack_dynamic &stack,int &e)
  54. {
  55. if(stack.base==stack.top)
  56. return;
  57. stack.top--;
  58. e=*stack.top;
  59. }
  60. int GetTop(SqStack_dynamic &stack)
  61. {
  62. if(stack.base!=stack.top)
  63. return *(stack.top-1);
  64. else
  65. return -1;
  66. }
  67. int main()
  68. {
  69. SqStack_dynamic stack;
  70. InitStack(stack);
  71. push(stack,2);
  72. push(stack,5);
  73. push(stack,10);
  74. std::cout<<"------dynamic stack-----"<<std::endl;
  75. int num;
  76. pop(stack,num);
  77. std::cout<<num<<" ";
  78. pop(stack,num);
  79. std::cout<<num<<" ";
  80. pop(stack,num);
  81. std::cout<<num<<" ";
  82. stack_static stack_s;
  83. stack_s.push(5);
  84. stack_s.push(10);
  85. stack_s.push(20);
  86. std::cout<<std::endl;
  87. std::cout<<"------static stack-----"<<std::endl;
  88. int num_s;
  89. stack_s.pop(num_s);
  90. std::cout<<num_s<<" ";
  91. stack_s.pop(num_s);
  92. std::cout<<num_s<<" ";
  93. stack_s.pop(num_s);
  94. std::cout<<num_s<<" ";
  95. return 0;
  96. }

 3.树

1.定义

树是指由 n(n≥0)个结点组成的有穷集合 D 与 D 上的关系的集合 R构成的结构,通常我们用 T 表示。树需要满足以下 3 个条件:

  • 当 n=0 时,该结点集合为空,该树被称为空树
  • 在任意的非空树中,有且仅有一个根结点 root。
  • 当 n>1 时 ,除根结点以外的其余结点可以分为 m(m>0)个不相交的子集D1,D2,D3,…,Dm, 其中每一个这样的子集 Di(i≤m)本身又是一棵树, 称为根结点 root的子树

注意

  • 树的定义是一个递归定义,因为树是由根结点子树构成的,而每一个子树也是一棵树。
  • 从图中我们还了解,树结构在形式上最主要的特点就是分层特点具有一定的排列顺序
     

 2.树的表示方法

  • 树形表示法

  • 文氏图表示法

3.基本术语

  • 结点的度

结点拥有的直接子树数目。如图 A结点的度为3,B结点的度为2,c结点的度为1,D结点的度为3,E、F、G、H、I 以及J度都为0

  • 树的度

树中各结点度的最大值称为该树的度。如上图,树的度为3.

  • 分支结点

度不为 0 的结点称为分支结点或普通结点。

  • 叶子结点

度为 0 的结点称为叶子结点或终端结点。由此可知叶子结点没有子结点。

  • 结点的层次

从树的根结点开始,根结点为第 1 层,根结点的子结点为第 2 层,第 2 层结点的子结点为第 3 层……

  • 树的深度

树中结点的最大层次数被定义为该树的深度或高度。

  • 森林

n(n≥0)棵不相交的树的集合称为森林。

4.基本结构 

  • 二叉树具有的几种形态

5.性质 

6. 存储方式

  • 顺序存储

顺序存储将二叉树的每一个节点和数组的编号一一对应,根据这个编号,可以找到该结点的父结点和孩子结点

BinaryTree[0]表示该树的根结点,从根结点开始我们可以按照性质 6 去检索该树的所有结点,比如一个有 20 个结点的
二叉树, 根据性质 6 编号为 10 的结点的父结点为编号为 5 的结点,其左孩子结点为编号为20 的结点,其没有右孩子结点。

由此可以看出:

  • 如果二叉树是一棵完全二叉树的话,顺序结构的优点就非常明显,它能紧凑的存储二叉树,而且可以随机存取二叉树的某个结点,只需要根据性质 6 计算出该结点的元素下标即可;
  • 如果是非完全二叉树,则顺序存储结构就存在空间的浪费,它会为不存在的结点分配空间,而且如果二叉树规模很大,在实际应用中,内存里也很难找出相应的连续存储空间。
     
  • 链式存储

二叉树的节点一般定义为:数据部分、左子树指针右子树指针,用指针将节点串起来,其中 l 表示左孩子指针, r 表示右孩子指针,∧表示空指针

优点:

  • 能够很直观地表示二叉树的逻辑结构;
  • 在二叉树不是完全二叉树的时候,链式结构不会像顺序存储结构一样产生空结点,而且链式存储结构能很好地利用内存中的碎片空间,提高内存空间利用效率

缺点:

  • 链式存储结构不能随机存取某个结点,要找到某个结点,必须从根结点开始沿着指针往叶子结点遍历
     

7.基本操作

参考:

  • 构建一棵树,即初始化操作
  1. #include<iostream>
  2. using namespace std;
  3. class BinaryTreeNode{
  4. public:
  5. //init
  6. BinaryTreeNode(){
  7. data=NULL;
  8. lchild=NULL;
  9. rchild=NULL;
  10. }
  11. BinaryTreeNode(int n){
  12. data=new int;
  13. *data=n;
  14. lchild=NULL;
  15. rchild=NULL;
  16. }
  17. private:
  18. int *data;//data
  19. BinaryTreeNode* lchild;//left child tree
  20. BinaryTreeNode* rchild;//right child tree
  21. };
  22. int main()
  23. {
  24. BinaryTreeNode bt(5);
  25. return 0;
  26. }
  • 前序遍历(根、左、右)
  1. //递归
  2. void preorderTraversal(BinaryTreeNode *node)
  3. {
  4. if(!node)
  5. return;
  6. std::cout<<node->data<<" ";
  7. preorderTraversal(node->lchild);
  8. preorderTraversal(node->rchild);
  9. }
  10. //迭代
  11. void preoder(BinaryTreeNode *root)
  12. {
  13. BinaryTreeNode *cur=root;
  14. std::stack<BinaryTreeNode *>s;
  15. while(cur||!s.empty())
  16. {
  17. //遍历直到最左叶子节点
  18. while(cur)
  19. {
  20. std::cout<<cur->data<<" ";
  21. s.push(cur);
  22. cur=cur->lchild;
  23. }
  24. //while结束时,cur=NULL
  25. //cur为左子节点
  26. cur=s.top();
  27. s.pop();
  28. cur=cur->rchild;
  29. }
  30. }
  • 中序遍历(左、根、右)
  1. void midorderTraversal(BinaryTreeNode *node)
  2. {
  3. if(!node)
  4. return;
  5. preorderTraversal(node->lchild);
  6. std::cout<<node->data<<" ";
  7. preorderTraversal(node->rchild);
  8. }
  9. void midoder(BinaryTreeNode *root)
  10. {
  11. BinaryTreeNode *cur=root;
  12. std::stack<BinaryTreeNode *>s;
  13. while(cur||!s.empty())
  14. {
  15. //遍历直到最左叶子节点
  16. while(cur)
  17. {
  18. s.push(cur);
  19. cur=cur->lchild;
  20. }
  21. //while结束时,cur=NULL
  22. //cur为左子节点
  23. cur=s.top();
  24. std::cout<<cur->data<<" ";
  25. s.pop();
  26. cur=cur->rchild;
  27. }
  28. }
  • 后序遍历(左、右、根)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/516236
推荐阅读
相关标签
  

闽ICP备14008679号