常用数据结构
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);
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;
}
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);
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);//删除略复杂,需要考虑是叶子节点,还是有几个孩子节点的情况,还涉及到找最小子结点移动到删除的父节点。
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);
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);
分类: 数据结构及算法