一. 线性表
1.顺序表
特点:逻辑上相邻,物理上也相邻,存取方便
#include<stdio.h>
#include<stdlib.h>
#define ElemType int //元素类型
#define Status int //函数类型
#define List_Size 100 // 存储空间初始量
#define List_Increase 10 // 存储空间增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef struct SqList {
ElemType *elem; // 数据元素存储空间的首地址
int length, listsize; // 线性表的当前长度和存储容量
}S;
Status Init_List(SqList &L);//构造一个空线性表
Status Destroy_List(SqList &L);//销毁线性表
Status Clear_List(SqList &L);//重置为空表
Status ListEmpty(SqList L);//表空true,否则false
Status ListLength(SqList L);//L中元素个数
Status ListInsert(SqList &L, int i, ElemType e);//在第i个位置前插入元素e
Status ListDel(SqList &L, int i, ElemType &e);//删除第i个元素,返回其值
Status GetElem(SqList L, int i, ElemType &e);//用e放回第i个元素的值
Status LocateElem(SqList L, ElemType e, Status(*compare)(ElemType, ElemType));//返回第一个与e满足compare关系的元素位序
int main()
{
SqList L;
Init_List(L);
for(int i = 1; i <= 5; i ++)
ListInsert(L, 1, i);
for(int i = 1; i <= 5; i ++)
printf("%d ", *(L.elem + i - 1));
return 0;
}
Status Init_List(SqList &L){
L.elem = (ElemType*)malloc(List_Size*sizeof(ElemType));//分配空间并返回第一个字节地址
//L.elem = new ElemType[List_size];
if(!L.elem) exit(OVERFLOW);
L.length = 0;
L.listsize = List_Size;
return OK;
}
Status Destroy_List(SqList &L){
free(L.elem);//释放内存
L.elem = NULL;
L.length = 0;
L.listsize = 0;
return OK;
}
Status Clear_List(SqList &L){
L.length = 0;
return OK;
}
Status List_Empty(SqList L){
if(L.length == 0) return TRUE;
else return FALSE;
}
Status ListLength(SqList L){
return L.length;
}
Status ListInsert(SqList &L, int i, ElemType e){
if(i < 1 || i > L.length + 1) return ERROR;//i不合法
if(L.length >= L.listsize){//存储空间满,增加分配
ElemType *newbase = (ElemType*) realloc (L.elem, (L.listsize + List_Increase)*sizeof(ElemType));
if(!newbase) exit(OVERFLOW);
L.elem = newbase;
L.listsize += List_Increase;
}
ElemType *q;
ElemType *p;
q = L.elem + i - 1; //插入位置
//q = &(L.elem[i - 1]);
//往后移
for(p = &(L.elem[L.length - 1]); p >= q; p --){
*(p + 1) = *p;
}
*q = e;
L.length ++;
}
Status ListDel(SqList &L, int i, ElemType &e){
if(i < 1 || i > L.length) return ERROR;
ElemType *q, *p;
q = L.elem + i - 1;//删除位置
e = *q;//删除元素的值
p = L.elem + L.length - 1;
for(q ++; q <= p; q ++){ //i后面的左移
*(q - 1) = *q;
}
L.length --;
return OK;
}
Status GetElem(SqList L, int i, int &e){
if(i < L.length || i > L.length) exit(ERROR);
e = *(L.elem + i - 1);
return OK;
}
Status LocateElem(SqList L, ElemType e, Status(*compare)(ElemType, ElemType)){
int i = 1;
ElemType *q;
q = L.elem;
while(i <= L.length && !compare(*q ++, e)){
i ++;
}
if(i <= L.length) return i;
else return 0;
}
2.链表
特点:逻辑上相邻,物理上不一定相邻,插删方便
(*a).b 等价于 a->b
#include<stdio.h>
#include<stdlib.h>
#define ElemType int //元素类型
#define Status int //函数类型
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef struct LNode {
ElemType data; //数据域
struct LNode *next; //指针域
} LNode, *LinkList;
Status InitList(LinkList &L); //构造一个空的单链表
Status DestroyList(LinkList &L); //销毁顺序线性表L
Status ClearList(LinkList &L); //单链表清空
Status ListEmpty(LinkList L); //单链表判空
int ListLength(LinkList L); //求链表长度
Status GetElem(LinkList L, int i, ElemType &e); //取单链表中位序为i的元素值
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType,ElemType)); //定位操作,返回L中第1个与e满足关系compare()的数 据元素的位序。若未找到则返回0
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e); //求前驱操作
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e); //求后继操作
Status ListInsert(LinkList &L, int i, ElemType e); //在L中第i个位置之前插入新的数据元素e
Status ListDelete(LinkList L, int i, ElemType &e); //在L中删除第i个位置元素,由e返回其值
Status comp(ElemType c1,ElemType c2); //数据元素判定函数(相等为TRUE,否则为FALSE)
void display(LinkList L); //遍历
int main()
{
LinkList L; //单链表的头指针
InitList(L);
for(int i = 1; i <= 5; i ++)
ListInsert(L, 1, i);
display(L);
return 0;
}
Status InitList(LinkList &L)
{
L = (LinkList)malloc(sizeof(struct LNode)); //产生头结点,并使L指向此头结点
if(!L) // 存储分配失败
exit(OVERFLOW);
L -> next = NULL; // 指针域为空
return OK;
}
Status DestroyList(LinkList &L)
{
LinkList q;
while(L)
{
q = L -> next;
free(L);
L = q;
}
return OK;
}
Status ClearList(LinkList &L)
{ // 初始条件:线性表L已存在。操作结果:将L重置为空表
LinkList p, q;
p = L -> next; // p指向第一个结点
while(p) // 没到表尾
{
q = p -> next;
free(p);
p = q;
}
L -> next = NULL; // 头结点指针域为空
return OK;
}
Status ListEmpty(LinkList L)
{
if(L-> next) // 非空
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L){
int n = 0;
LinkList p = L -> next;
while(p){
n ++;
p = p -> next;
}
return n;
}
Status ListInsert(LinkList &L, int i, ElemType e){
LinkList p = L;
int j = 0;
while(p && j < i - 1){
p = p -> next;
j ++;
}
if(!p || j > i - 1) return ERROR;
LinkList s = (LinkList) malloc (sizeof(LNode));
s -> data = e;
s -> next = p -> next;
p -> next = s;
return OK;
}
Status ListDelete(LinkList L, int i, ElemType &e)
{ /* 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */
int j = 0;
LinkList p = L, q;
while(p -> next && j < i - 1) // 寻找第i个结点,并令p指向其前趋
{
p = p -> next;
j ++;
}
if(!p -> next || j > i-1) /* 删除位置不合理 */
return ERROR;
q = p -> next; /* 删除并释放结点 */
p -> next = q -> next;
e = q -> data;
free(q);
return OK;
}
void display(LinkList head)
{
LinkList p = head->next;
while(p != NULL) //注意陈列打印的条件
{
printf("%d ", p -> data);
p = p -> next;
}
return;
}
Status GetElem(LinkList L, int i, ElemType &e) /* 算法2.8 */
{
int j = 1; // j为计数器
LinkList p = L -> next; // p指向第一个结点
while(p && j < i) // 顺指针向后查找,直到p指向第i个元素或p为空
{
p = p -> next;
j ++;
}
if(!p || j > i) // 第i个元素不存在
return ERROR;
e = p -> data; // 取第i个元素
return OK;
}
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{
// 操作结果: 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, 返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE
LinkList q, p = L -> next; // p指向第一个结点
while(p -> next) // p所指结点有后继
{
q = p -> next; // q为p的后继
if(q -> data == cur_e)
{
pre_e = p -> data;
return OK;
}
p = q; //p向后移
}
return INFEASIBLE;
}
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{
// 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,返回OK;否则操作失败,next_e无定义,返回INFEASIBLE
LinkList p = L -> next; // p指向第一个结点
while(p -> next) // p所指结点有后继
{
if(p -> data == cur_e)
{
next_e = p -> next -> data;
return OK;
}
p = p -> next;
}
return INFEASIBLE;
}
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType)){
int i = 0;
LinkList p = L -> next;
while(p){
i ++;
if(compare(p -> data, e)) return i;
p = p -> next;
}
return ERROR;
}
Status comp(ElemType c1, ElemType c2)
{ /* 数据元素判定函数(相等为TRUE,否则为FALSE) */
if(c1 == c2)
return TRUE;
else
return FALSE;
}
二. 栈和队列
1.队列
//头节点不存数据,便于操作
#include <stdio.h>
#include<malloc.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
typedef struct LinkQueue{
LinkList front, rear; //对头队尾指针
}LinkQueue;
//如果不能用引用,形参用指针类型,(LinkQueue *Q), 函数中的前也要加*,下面函数中的e也一样
Status InitQueue(LinkQueue &Q){ //初始化
Q.front = Q.rear = (LinkList) malloc(sizeof(LNode)); //强转为LinkList指针
if(!Q.front) exit(OVERFLOW);
Q.front -> next = NULL;
return OK;
}
Status DestroyQueue(LinkQueue &Q){ //销毁
while(Q.front){ //非空
LinkList p = Q.front -> next;
free(Q.front);
Q.front = p;
}
return OK;
}
Status QueueInsert(LinkQueue &Q, ElemType e){ //入队
LinkList p = (LinkList)malloc(sizeof(LNode));
if(!p) exit(OVERFLOW);
p -> data = e;
p -> next = NULL;
Q.rear -> next = p; //入队,把p接在后面
Q.rear = p; //把队尾更新
return OK;
}
Status DeQueue(LinkQueue &Q, ElemType &e){ //出队
if(Q.front == Q.rear) return ERROR;
LinkList p = Q.front -> next;
e = p -> data;
Q.front -> next = p -> next; //ne[idx] = ne[ne[idx]]那个意思;
if(Q.rear == p) Q.rear = Q.front; //要出队的对头已经是最后一个元素了
free(p); //c++可以delete p;
return OK;
}
Status GetHead(LinkQueue &Q, ElemType &e){ //获取对头,不出队
if(Q.rear == Q.front) return ERROR;
e = Q.front -> next -> data;
return OK;
}
int QueueLength(LinkQueue &Q){
int len = 0;
LinkList p;
if(Q.front == Q.rear) return 0;
p = Q.front -> next;
while(p){
len ++;
p = p -> next;
}
return len;
}
Status visit(LinkQueue Q){
if(Q.front == Q.rear) return ERROR;
LinkList p = Q.front -> next;
while(p){
printf("%d ", p -> data);
p = p -> next;
}
return OK;
}
int main()
{
LinkQueue Q;
InitQueue(Q); //形参用的指针类型的话,传入要加引用
for(int i = 1; i <= 3; i ++) QueueInsert(Q, i);
visit(Q);
printf("\n");
printf("len: %d\n", QueueLength(Q));
int x;
DeQueue(Q, x);
printf("first: %d\n", x);
return 0;
}
2.栈
#include<stdio.h>
#include<stdlib.h>
#define ElemType int //元素类型
#define Status int //函数类型
#define Init_Size 100 // 存储空间初始量
#define Stack_Increase 10 // 存储空间增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef struct{
ElemType *base, *top;
int stacksize;
}SqStack;
Status InitStack(SqStack &S); //构造一个空栈
Status StackEmpty(SqStack S); //栈空,返回true
Status StackLength(SqStack S);
Status GetTop(SqStack S, ElemType &e); // 取栈顶,不pop
Status Push(SqStack &S, ElemType &e);
Status Pop(SqStack &S, ElemType &e);
int main()
{
SqStack S;
InitStack(S);
for(int i = 1; i <= 5; i ++)
Push(S, i);
while(!StackEmpty(S)){
int e;
GetTop(S, e);
Pop(S, e);
printf("%d ", e);
}
}
Status InitStack(SqStack &S){
S.base = (ElemType *)malloc(Init_Size * sizeof(ElemType));
if(!S.base) exit(OVERFLOW);
S.top = S.base;
S.stacksize = Init_Size;
return OK;
}
Status GetTop(SqStack S, ElemType &e){
if(S.top == S.base) return ERROR;
e = *(S.top - 1);
return OK;
}
Status StackEmpty(SqStack S){
return S.base == S.top ? OK : ERROR;
}
Status StackLength(SqStack S){
if(S.base == S.top)
return 0;
else
return S.top - S.base;
}
Status Push(SqStack &S, ElemType &e){
if(S.top - S.base >= S.stacksize){ //栈满,分配空间
S.base = (ElemType *)realloc(S.base, (S.stacksize + Stack_Increase) * sizeof(ElemType));
if(!S.base) exit(OVERFLOW);
S.top = S.base + S.stacksize;
S.stacksize += Stack_Increase;
return OK;
}
*S.top ++ = e; //*S.top = e, S.top ++;
return OK;
}
Status Pop(SqStack &S, ElemType &e){
if(S.top == S.base) return ERROR; //栈空
e = * --S.top; //S.top --, e = *S.top
return OK;
}
三. 树和二叉树
1.二叉树
先序遍历构建二叉树,前中后序遍历(递归)
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define INFEASIBLE -2
#define NULL 0
#define Status int
#define ElemType char
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
BiTree CreatBiTree()
{
ElemType ch;
scanf("%c", &ch);
BiTree T;
if(ch == '#') T = NULL;
else{
T = (BiTree)malloc(sizeof(BiTNode));
if(!T) exit(OVERFLOW);
T -> data = ch;
T -> lchild = CreatBiTree();
T -> rchild = CreatBiTree();
}
return T; //返回根节点
}
void Pre(BiTree T){
if(T){
printf("%c ", T -> data);
if(T -> lchild) Pre(T -> lchild);
if(T -> rchild) Pre(T -> rchild);
}
}
void Mid(BiTree T){
if(T){
if(T -> lchild) Mid(T -> lchild);
printf("%c ", T -> data);
if(T -> rchild) Mid(T -> rchild);
}
}
void Post(BiTree T){
if(T){
if(T -> lchild) Post(T -> lchild);
if(T -> rchild) Post(T -> rchild);
printf("%c ", T -> data);
}
}
int main()
{
BiTree T;
T = CreatBiTree();
Pre(T);
printf("\n");
Mid(T);
printf("\n");
Post(T);
}
非递归遍历
——待更新——
由前中或中后创建二叉树
——待更新——
2.哈夫曼树
哈夫曼树的结点的度数为0或2,没有度为1的结点
包含n颗树的森林要经过n - 1次合并形成哈夫曼树,共产生n - 1个新节点,所以包含n个叶子结点的哈夫曼树中共有2n - 1个结点