数据结构半学期复习

**数据结构**
1、**线性结构**
  1.1 线性表
  1.2 堆栈
  1.3 队列
2、**树**
   2.1 二叉树
   2.2 二叉搜索树/二叉查找树
   2.3 平衡二叉树
   2.4 树的应用
      2.4.1 堆
      2.4.2 哈夫曼树
      2.4.3 集合
3、**散列查找**
4、**图**
5、**排序**

1.1 线性表

顺序存储

顺序表类型:

typedef int Position;
typedef struct LNode * PtrToLNode;
struct LNode
{
	ElementType Data[MAXSIZE];
	Position Last;
};
typedef PtrToLNode List;

顺序表的初始化建造一个空表

List MakeEmpty()
{
	List L;
	L = (List)malloc(sizeof(struct LNode));
	          // for(int i=0;i<n;i++)
	             // L->Data[i]=a[i];
	          // L->Last = n;
	L->Last = -1;
	return L;
}

顺序表的查找:

#define ERROR -1
Position Find(List L, ElementType X)
{
	Position i=0;
	while(i<=L->Last && L->Data[i]!=X) //Last指向最后一个元素 
	  i++;
	if(i>L->Last)
	  return ERROR;
	else
	  return i; //找到返回对应下标 
}

顺序表的插入:

bool Insert(List L, ElementType X, int i)
{
	Position j;
	
	if(L->Last == MAXSIZE-1)
	{
		printf("表满\n");
		return false;
	}
	if(i<1 || i>L->Last+2)
	{
		printf("位序不合法\n");
		return false;
	}
	
	for(j=L->Last;j>=i-1;j--)
//从最后的元素开始查找,第i个位置下标是i-1 
	  L->Data[j+1] = L->Data[j];
	L->Data[i-1] = X;//第i个位置的数为插入的数据 
	L->Last++;//更新Last 
	return true;
}

顺序表的删除:

bool Delete(List L, int i)
{
	Position j;
	
	if(i<1 || i>L->Last+1)
	{
		printf("位序%d不存在元素\n",i);
		return false;
	}
	
	for(j=i; j<=L->Last ;j++)
//j从第i个元素的后一位开始指 
		L->Data[j-1] = L->Data[j];
	L->Last--;//更新Last 
	return true;
}

链式表的结构定义:

typedef struct LNode * PtrToLNode;
struct LNode
{
	ElementType Data;
	PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;

链式表求表长

int Length(List L)
{
	Position p;
	int cnt = 0;
	p = L;//p指向表的第一个结点
	while(p)
	{
		p = p->Next ;
		cnt++;
	}
	return cnt;
}

链式表的按序号查找:

#define ERROR -1
ElementType FindKth(List L, int K)
{
	Position p;
	int cnt = 1;//从位序1开始 
	p = L;//p指向L的第一个结点
	while(p && cnt<K) 
	{
		p = p->Next ;
		cnt++;
	}
	if((cnt == K) && p)
	  return p->Data ;//找到第K个元素 
	else
	  return ERROR;
}

链式表的按值查找:

#define ERROR NULL
Position Find(List L, ElementType X)
{
	Position p = L;//p指向L的第一个结点
	while(p && p->Data != X)
	  p = p->Next ;
//在没找到X且在链尾之前 就一直往下找 
	if(p)
	  return p; 
	else
	  return ERROR; 
}

链式表的插入:

#define ERROR NULL
List Insert(List L, ElementType X, int i)
{
	Position tmp , pre;
	//分配空间,存入X 
	tmp = (Position)malloc(sizeof(struct LNode));
	tmp->Data = X;
	
	if(i == 1)//在表头插入 
	{
		tmp->Next = L;
		return tmp;
	}
	else
	{
		int cnt = 1;
		pre = L;//pre指向L的第一个结点
		
		while( pre && cnt<i-1 )
		{
			pre = pre->Next ;
			cnt++;
		}

		if(pre == NULL || cnt!=i-1)
		{//没找到,找到链尾了 或者是 不是因为cnt==i-1结束的循环 
			printf("插入位置参数错误\n");
			free(tmp);
			return ERROR;
		}
		else
		{//找到了pre 
			tmp->Next = pre->Next ;
			pre->Next = tmp;
			return L; 
		}
	}
}

带头结点的链式表的插入:

bool Insert(List L, ElementType X, int i)
{
	Position tmp , pre;
	int cnt = 0;//有头结点的时候 
	
	pre = L;//pre指向表头 
	
	while(pre && cnt<i-1)//第i个位置的前一个结点i-1 
	{
		pre = pre->Next ;
		cnt++;
	}
	
	if(pre == NULL || cnt!=i-1)
	{//没找到,找到链尾了 或者是 不是因为cnt==i-1结束的循环 
		printf("插入位置参数错误\n");
		return false;
	}
	else
	{
//找到了待插结点的前一个结点pre,若i==1,pre就指向表头 
		tmp = (Position)malloc(sizeof(struct LNode));
	    tmp->Data = X;
	    tmp->Next = pre->Next ;
	    pre->Next = tmp;
	    return true;
	}
}

带头结点的链式表的删除:

bool Delete(List L, int i)
{
	Position pre;
	int cnt = 0;
	pre = L;//pre指向表头 
	
	while(pre && cnt<i-1)
	{
		pre = pre->Next ;
		cnt++;
	}
	if(pre==NULL || cnt!=i-1 || pre->Next == NULL)
	{// pre->Next == NULL !!!
	//所找结点或位序为i的结点不再L中 
		printf("删除位置参数错误\n");
		return false;
	}
	else
	{
		pre->Next = pre->Next->Next ;
		//课本用了一个中间量tmp
		return true;
	}
}

1.2 堆栈 先进后出

顺序栈类型:

typedef int Position;
typedef struct SNode * PtrToSNode;
struct SNode
{
	ElementType *Data;//存储元素的数组 
	Position Top;//栈顶指针 
	int MaxSize;//堆栈最大容量 
};
typedef PtrToSNode Stack;

顺序栈的创建:

Stack CreateStack(int MaxSize)
{
	Stack S = (Stack)malloc(sizeof(struct SNode));
	S->Data = (ElementType*)malloc(MaxSize * sizeof(ElementType));
	S->Top = -1;
	S->MaxSize = MaxSize;
	return S;
}

顺序栈的入栈操作:

bool IsFull(Stack S)
{
	return (S->Top == S->MaxSize-1);
}
bool Push(Stack S, ElementType X)
{
	if(IsFull(S)) //先判断是否栈满
	{
		printf("堆栈满\n");
		return false;
	}
	else
	{
		S->Data[++(S->Top)] = X;
	//先++栈顶指针,再赋值 
		return true;
	}
}

顺序栈的出栈操作:

bool IsEmpty(Stack S)
{
	return (S->Top == -1);
}
ElementType Pop(Stack S)
{
	if(IsEmpty(S))//先判断是否空 
	{
		printf("堆栈空\n");
		return ERROR;
		//前面得先定义ERROR的值,标志错误 
	}
	else
	{
		return (S->Data[(S->Top)--]);
	//先取数,再栈顶指针--
	}
}

链栈的类型:

typedef struct SNode * PtrToSNode;
struct SNode
{
	ElementType Data;//存储元素
	PtrToSNode Next;
};
typedef PtrToSNode Stack;

带头结点的链栈操作实现:

Stack CreateStack()
{
	Stack S;
	S = (Stack)malloc(sizeof(struct SNode));
	S->Next = NULL;//带头结点 
	return S;
}
bool Push(Stack S, ElementType X)
{
	Stack tmp;
	
	tmp = (Stack)malloc(sizeof(struct SNode));
	tmp->Data = X;
	tmp->Next = S->Next ;
	S->Next = tmp;
	//将元素X压入堆栈,头插法 
	return true;
}
bool IsEmpty(Stack S)
{
	return(S->Next == NULL);
}
ElementType Pop(Stack S)
{
	Stack First;
	ElementType Topelem;//返回删除元素的值 
	
	if(IsEmpty(S))
	{
		printf("堆栈空\n");
		return ERROR;
	}
	else
	{
		First = S->Next ;
	//S指向的是头结点,First指向S的下一个结点 
		Topelem = First->Data ;
	//存下First指向的结点的数据 
		S->Next = S->Next->Next ;
		free(First);
		return Topelem;
	}
}

1.3 队列 先进先出

队列的顺序存储结构定义:

typedef int ElementType;
typedef int Position;
typedef struct QNode * PtrToQNode;
struct QNode
{
	ElementType *Data;
	Position Front,Rear;
	int MaxSize;
};
typedef PtrToQNode Queue;

循环队列的创建:

Queue CreateQueue(int MaxSize) //创建 
{
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	Q->Data=(ElementType)malloc(MaxSize*sizeof(ElementType));
	Q->Front = Q->Rear = 0;
	Q->MaxSize = MaxSize;
	return Q;
}

循环队列的入队:

bool IsFull(Queue Q) //队满 
{
	return ((Q->Rear+1)%Q->MaxSize==Q->Front);
}
bool AddQ(Queue Q, ElementType X) //入队 
{
	if(IsFull(Q))
	{
		printf("队列满\n");
		return false;
	}
	else
	{
		Q->Rear = (Q->Rear+1) % Q->MaxSize ;
		//入队是Rear指针在变
		Q->Data[Q->Rear] = X;
		return true; 
	}
}

循环队列的出队:

typedef -1 ERROR;
bool IsEmpty(Queue Q)
{
	return (Q->Front==Q->Rear);
}
ElementType DeleteQ(Queue Q) //删除 
{
	if(IsEmpty(Q))
	{
		printf("队列空\n");
		return ERROR;
	}
	else
	{
		Q->Front = (Q->Front+1)%Q->MaxSize ;
		//出队是Front指针在变
		return Q->Data[Q->Front]; 
	}
}

链式队列的结构定义:

typedef int ElementType;
typedef struct Node * PtrToNode;
struct Node
{
	ElementType Data;
	PtrToNode Next;
};

typedef int Position;
typedef struct QNode * PtrToQNode;
struct QNode
{
	Position Front,Rear;
	int MaxSize;
};
typedef PtrToQNode Queue;

链式队列的删除:

bool IsEmpty(Queue Q)
{
	return (Q->Front == NULL);
}
ElementType DeleteQ(Queue Q)
{
	Position frntc;
	ElementType frntelm;
	if(IsEmpty(Q))
	{
		printf("队列空\n");
		return ERROR;
	}
	else
	{
		frntc = Q->Front ;
		if(Q->Front == Q->Rear ) //队列里只有一个元素 
		   Q->Front = Q->Rear = NULL;
		else
		{
			Q->Front = Q->Front->Next ; 
		}
		frntelm = frntc->Data ; 
		free(frntc);
		return frntelm;
	}
}

2.1 二叉树

先列一些树的基本术语:
结点的度,树的度
叶结点,父结点,子结点,兄弟结点,祖先结点,子孙结点
结点的层次,树的深度
分支,路径,路径长度

度之和 = 分支数(边数)= 结点数-1
第 i 层的最大结点数 = 2^(i-1)
深度为 k 的二叉树有最大结点总数 2^k-1

二叉树的链表结构:

typedef int ElementType;
typedef struct TNode * Position;
typedef Position BinTree;
struct TNode
{
	ElementType Data;
	BinTree Left;
	BinTree Right;
};

二叉树的中序遍历:

void InoderTraversal(BinTree BT)
{
	if(BT)
	{
		InoderTraversal(BT->Left);
		printf("%d",BT->Data);
		InoderTraversal(BT->Right);
	}
}

先序遍历、后序遍历也很好写,这里就不列了

在这里先记录非递归中序遍历,往后有时间再写吧

二叉树的层序遍历:

void LevelorderTraversal(BinTree BT)
{
	Queue Q;
	BinTree T;
	if(!BT)  return ; //空树直接返回 
	
	Q=CreateQueue(); //创建空队列 
	Add(Q,BT);
	
	while(!IsEmpty(Q))
	{
		T = DeleteQ(Q);
		printf("%d",T->Data);
		if(T->Left)  Add(Q,T->Left);
		if(T->Right)  Add(Q,T->Right);
	}
}

输出结点:

void PreorderPrintLeaves(BinTree BT)
{
	if(BT)
	{
		if(!BT->Left && !BT->Right) //叶结点
		    printf("%d",BT->Data);
		PreorderPrintLeaves(BT->Left);
		PreorderPrintLeaves(BT->Right);
	}
}

求二叉树的树高:

int GetHeight(BinTree BT)
{
	int HL,HR,MaxH;
	if(BT)
	{
		HL = GetHeight(BT->Left);
		HR = GetHeight(BT->Right);
		MaxH = HL > HR ? HL : HR;
		return (MaxH+1);
	}
	else return 0;
}

用链表的方式实现二叉树的存储和基本操作,包括CreateBinTree()、PreorderTraversal()、InorderTraversal()、PostorderTraversal()等操作。

//用链表的方式实现二叉树的存储和基本操作,
//包括 CreateBinTree()、PreorderTraversal()、InorderTraversal()、PostorderTraversal()等操作。
#include<stdio.h>
#include<stdlib.h>
#define NoInfo '0'
#define QUEUESIZE 50

typedef char ElementType; //字符型数据 
typedef struct TNode * Position;
typedef Position BinTree;

struct TNode  //树的结构 
{
	ElementType Data;
	BinTree Left;
	BinTree Right;
};

BinTree CreateBinTree() //树的创建 
{
	ElementType Data;
	BinTree BT,T;
	BinTree DataQueue[QUEUESIZE];//??? 
	int front = 0;
	int rear= 0;
	int queuel = 0;
	
	
	scanf("%c",&Data);
	if(Data != NoInfo) //根结点的创建 
	{
		BT=(BinTree)malloc(sizeof(struct TNode));
		BT->Data = Data;
		BT->Left = BT->Right = NULL;
		DataQueue[rear] = BT; // 
		rear = (rear+1) % QUEUESIZE; //更新 rear 的值 
		queuel++; //队列长度 ++ 
	}
	else
	{
		return NULL;
	}
	
	while(queuel > 0) // 
	{
		T = DataQueue[front]; 
		front = (front+1) % QUEUESIZE; //出队 
		queuel--; //队列长度 -- 
		
		scanf("%c",&Data); //输入左子树 
		if(Data == NoInfo)
		{
			T->Left = NULL;
		}
		else
		{
			T->Left = (BinTree)malloc(sizeof(struct TNode));
			T->Left->Data = Data;
			T->Left->Left = T->Left->Right = NULL;
			DataQueue[rear] = T->Left ; //把数据放入 
			rear=(rear+1) % QUEUESIZE;  //更新 rear 
			queuel++;  //队列长度 ++ 
		}
		
		scanf("%c",&Data); //输入右子树 
		if(Data == NoInfo)
		{
			T->Right = NULL;
		}
		else
		{
			T->Right = (BinTree)malloc(sizeof(struct TNode));
			T->Right->Data = Data;
			T->Right->Left = T->Right->Right = NULL;
			DataQueue[rear] = T->Right ; //
			rear=(rear+1) % QUEUESIZE; //
			queuel++;  //
		}
	}
	return BT; 
}

void PreorderTraversal(BinTree BT)
{
	if(BT)
	{
		printf("%c",BT->Data );
		PreorderTraversal(BT->Left);
		PreorderTraversal(BT->Right);
	}
}
void InorderTraversal(BinTree BT)
{
	if(BT)
	{
		InorderTraversal(BT->Left);
		printf("%c",BT->Data );
		InorderTraversal(BT->Right);
	}
}
void PostorderTraversal(BinTree BT)
{
	if(BT)
	{
		PostorderTraversal(BT->Left);
		PostorderTraversal(BT->Right);
		printf("%c",BT->Data );
	}
}

int main()
{
	BinTree BT = CreateBinTree();
	PreorderTraversal(BT);
	printf("\n");
	InorderTraversal(BT);
	printf("\n");
	PostorderTraversal(BT);
	return 0;
}

实现二叉搜索树和平衡二叉树的创建、插入和查找操作。

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 50

typedef int ElementType;
typedef struct BSTNode * BST; //搜索树的类型 
struct BSTNode //结点定义 
{
	ElementType Data;
	BST Left;
	BST Right;
};

BST InsertBST(BST Root, ElementType X)//BST的插入操作 
{
	if(Root == NULL) 
	{
		Root = (BST)malloc(sizeof(struct BSTNode));
		Root->Data = X;
		Root->Left = Root->Right = NULL;
	}
	
	else
	{
		if(X < Root->Data ) //左插 
		{
			Root->Left = InsertBST(Root->Left,X);
		}
		else if(X > Root->Data ) //右插 
		{
			Root->Right = InsertBST(Root->Right,X);
		}
	}
	return Root;
}

int FindBST(BST Root, ElementType X) //查找次数 
{
	if(Root == NULL)
		return 0;
	
	if(X < Root->Data ) //往左找 
		return 1+FindBST(Root->Left, X);
	else if(X > Root->Data ) //往右找 
		return 1+FindBST(Root->Right, X);
	else // X==Root->Data
		return 1;
}

typedef struct AVLNode * AVL; //平衡二叉树的类型 
struct AVLNode //结点定义 
{
	ElementType Data;
	AVL Left;
	AVL Right;
	int Height;//树高 
};

int GetHeight(AVL Root) //
{
	if(Root == NULL)
		return 0;

	else
		return Root->Height; //
}

int Max(int a, int b)
{
	return a>b ? a:b ;
}

AVL SingleLeftRotation(AVL A) //左单旋 
{
	AVL B = A->Left ;
	A->Left = B->Right ;
	B->Right = A;
	A->Height = Max(GetHeight(A->Left),GetHeight(A->Right)) + 1;
	B->Height = Max(GetHeight(B->Left),A->Height) + 1;
	return B;
}
AVL SingleRightRotation(AVL A) //右单旋 
{
	AVL B = A->Right ;
	A->Right = B->Left ;
	B->Left = A;
	A->Height = Max(GetHeight(A->Left),GetHeight(A->Right)) + 1;
	B->Height = Max(GetHeight(B->Right),A->Height) + 1;
	return B;
}

AVL DoubleLeftRightRotation(AVL A)
{
	A->Left = SingleRightRotation(A->Left);
	return SingleLeftRotation(A);
}
AVL DoubleRightLeftRotation(AVL A)
{
	A->Right = SingleRightRotation(A->Right);
	return SingleRightRotation(A);
}

AVL InsertAVL(AVL Root, ElementType X) //AVL的插入 
{
	if(Root == NULL)
	{
		Root = (AVL)malloc(sizeof(struct AVLNode));
		Root->Data = X;
		Root->Left = Root->Right = NULL;
		Root->Height = 1;
	}
	
	else
	{
		if(X < Root->Data ) //左插 
		{
			Root->Left = InsertAVL(Root->Left,X);
			if(GetHeight(Root->Left)-GetHeight(Root->Right)==2) //左插不平衡 
			{
				if(X < Root->Left->Data)
					Root = SingleLeftRotation(Root);
				else if(X > Root->Left->Data)
					Root = DoubleLeftRightRotation(Root);
			}
		}
		else if(X > Root->Data )
		{
			Root->Right  = InsertAVL(Root->Right,X);
			if(GetHeight(Root->Right) - GetHeight(Root->Left) == 2)
			{
				if(X > Root->Right->Data)
					Root = SingleRightRotation(Root);
				else if(X < Root->Right->Data )
					Root = DoubleRightLeftRotation(Root);
			}
		}
	}
	Root->Height = Max(GetHeight(Root->Left),GetHeight(Root->Right)) +1; //更新树高 
	return Root;
}

int FindAVL(AVL Root, ElementType X) //AVL的查找次数 
{
	int sum = 0;
	while(Root)
	{
	    sum++;
		if(X < Root->Data )
			Root = Root->Left ; //往左找 
		else if(X > Root->Data )
			Root = Root->Right ; //往右找 
		else
			break;
	}
	return sum;
}

int main()
{
	int n,i;
	ElementType a[MAXSIZE];
	BST BSTRoot=NULL;
	AVL AVLRoot=NULL;
	int BSTsum = 0;
	int AVLsum = 0;
	
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		scanf("%d",&a[i]); //用数组存放输入的数据 
		BSTRoot = InsertBST(BSTRoot,a[i]);
		AVLRoot = InsertAVL(AVLRoot,a[i]);
	}
	for(i=0;i<n;i++)
	{
		BSTsum += FindBST(BSTRoot,a[i]);
		AVLsum += FindAVL(AVLRoot,a[i]);
	}
	printf("%d\n%d",BSTsum,AVLsum);
	return 0;
}

2.4.1 堆

2.4.2 哈夫曼树

2.4.3 集合

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值