Fork me on GitHub
常用数据结构

常用数据结构

1. 链表

链表可以使用数组实现,也可以使用指针实现。用数组实现的链表的插入、删除操作需要O(N)的时间复杂度,很少使用。

用指针实现的链表,插入删除操作可以O(1)时间完成。

Code
链表结点定义
struct Node
{
  ElementType Element;
  Node* Next;
};
链表常用操作
int IsEmpty(Node* L);
int IsLast(Node* L);
Node* Find(ElementType X, Node* L);

Node* FindPrevious(ElementType X, Node* L);
void Delete(ElementType X, Node* L);
void Insert(ElementType X, Node* L, Node* P);

 

2. 栈

栈是插入删除操作都只能在一个位置上进行的表,该位置是表的末端,叫做顶。栈可以用数组实现,也可以用单链表。

结点定义
struct Node
{
  ElementType Element;
  Node* Next;
};
常用操作:链表实现的栈,入栈出栈操作就在表头进行。
int IsEmpty(Node* S);
void Push(ElementType Element, Node* S);
ElementType Top(Node* S);
void Pop(Node* S);

栈的数组实现是一种更为流行的实现方式
struct Stack
{
  int Capacity;
  int TopOfStack;
  ElementType *Array;
};

void Push(ElementType X, Stack* S)
{
  if(!IsFull(S))
     Error("Full stack");
  else
     S->Array[++S->TopOfStack]=X;
}

3. 队列

队列也是表,使用队列时插入在一端进行而删除则在另一端进行。使用循环数组实现。当队列为空时,size=0。

结点定义
struct Queue
{
  int Capacity;
  int Front;
  int Rear;
  int Size;
  ElementType *Array;
};
IsEmpty(Queue* Q);

//循环数组的size=Rear-Front+n*Capacity,n取能使0<size<Capacity的那一个
void Enqueue(ElementType X,Queue* Q)
{
  if(!IsFull(Q))
      Error("Full Queue");
  else
 {
  Q->size++;
  if(Q->Capacity-Q->Rear==1)
     Q->Rear=0;
  else
     Q->Rear++;
  Q->Array[Q->Rear]=X;
 }
}
void Dequeue(Queue* Q);

 

4. 二叉查找树

完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的节点都连续集中在最左边,这就是完全二叉树。

满二叉树:除最后一层外,每一层上的所有结点都有两个子结点(最后一层上的结点为叶子结点)。也可以这样理解,除叶子结点外的所有结点均有两个子结点。 

对于树中的每个结点X,它的左子树中所有关键字的值都小于X的关键字值,而它的右子树中所有关键字值大于X的关键字值。二叉树不一定是完全树,堆才是完全树。

结点定义
struct Node
{
  ElementType Element;
  Node* Left;
  Node* Right;
};
常用操作
Node* Find(ElementType X,Node* T); //重点掌握非递归算法
Node* Find(ElementType X,Node* T)
{
  if(T==NULL)
      Return NULL;
     while(T!=NULL)
{
     if(T->Element==X)
        return T;
     else if(T->Element>X)
        T=T->Left;
     else if(T->Element<X)
        T=T->Right;
     else
            return NULL;
}
}
Node* FindMin(Node* T);
Node* FindMax(Node* T);
Node* Insert(ElementType X,Node* T);//Insert略简单,可以使用递归实现
Node* Insert(ElementType X,Node* T)
{
   if(T==NULL)
      T=malloc(sizeof(struct Node));
      if(T==NULL)
        Error("Out of space!");
      else
      {
          T->Element=X;
          T->Left=T->Right=0;
      }
     else
     if(X<T->Element)
        T->Left=Insert(X,T->Left);
     else
     if(X>T->Right)
       T->Right=Insert(X,T->Right);
     return T;
}
Node* Delete(ElementType X,Node* T);//删除略复杂,需要考虑是叶子节点,还是有几个孩子节点的情况,还涉及到找最小子结点移动到删除的父节点。

 AVL树:一棵AVL树是其每个结点的左子树和右子树的高度最多差1的二叉查找树。

5. 堆

堆有两个性质,即结构性和堆序性。

结构性:堆是一棵被完全填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入。堆用数组实现,数组下标为0的元素不存数据,从下标1开始。对于数组任一位置i上的元素,其左儿子在位置2i上,右儿子在左儿子后的单元[2i+1]中,它的父亲则在位置[i/2]

堆序性:在每一个堆中,对于每个节点X,X的父亲中的关键字小于(或等于)X中的关键字,根节点除外。这个是对于小顶堆。

复制代码
堆结构定义
struct HeapStruct
{
  int Capacity;
  int size;
  ElementType *Elements;
};
堆常用操作
void Insert(ElementType X,HeapStruct* H);//涉及到上滤
{
  int i;
  if(!IsFull(H))
  {
    Error("PriorityQueue is full.");
    return;
  }
  for(i=++H->size;H->Elements[i/2]>X;i/=2)
    H->Elements[i]=H->Elements[i/2];
  H->Elements[i]=X;
}
ElementType DeleteMin(HeapStruct* H);//复杂,暂时不掌握了
ElementType FindMin(HeapStruct* H);
int IsFull(HeapStruct* H);
int IsEmpty(HeapStruct* H);
复制代码

 

 
posted on 2015-03-05 16:35  HackerVirus  阅读(270)  评论(0编辑  收藏  举报