數據結構——線性表(Code)

下面寫的代碼可能感覺會很亂,所以加上了目錄,意在爲了引導,也就是你需要回顧哪個算法,就能夠快速定位到該位置,如果從上往下去找的話,估計腦殼也疼死了。

一、線性表的基本操作

(一)順序表的基本操作
1. 順序表的結構體
#define MAX_SIZE 30				//設置順序表最大容量
typedef struct
{
	int data[MAX_SIZE];			//設置數據最大長度
	int length;					//設置數據當前長度

}Sqlist;
2. 順序表的查找
/*
method:
	順序表的查找
param:
	L 順序表
	n代表要查找的元素
*/

int Find_Elem(Sqlist L, int n)
{
	int result = 0;								//存放所查找到匹配值的下標
	for (result; result < n; result++)
	{
		if (L.data[result] == n)
			return result;
	}
	return ERROR;
}
3. 順序表的插入
/*
method:
	順序表的插入
param:
	sqlist 要操作的順序表
	pos    要插入的位置
	data   要插入的數據
*/
int Insert_Elem(Sqlist* sqlist, int pos, int data)
{
	int i = 0;
	if (pos<0 || pos>sqlist->length || sqlist->length == MAX_SIZE)		//這裏是判斷 如果 查詢位置不在線性表內,或者線性表長度滿了,則返回Error
		return ERROR;
	for (i = sqlist->length-1; i >= pos; i--)							//這個循環將pos位置後面的元素由後往前向後挪1個位置
		sqlist->data[i+1] = sqlist->data[i];
	sqlist->data[pos] = data;											//插入設定值
	sqlist->length += 1;												//線性表長度加1
	return OK;
}
4. 順序表的刪除
/*
method:
	順序表的刪除
param:
	sqlist	要操作的順序表
	pos		要刪除的位置
	num		存放刪除的元素
*/

int Delete_Elem(Sqlist* sqlist, int pos,int *num)						
{
	int i = pos;
	if (pos<0 || pos >sqlist->length)
		return ERROR;
	*num = sqlist->data[pos];											//得到刪除的值
	for (i; i < sqlist->length; i++)									//由前往後,pos位置後面的值依次往前移動
		sqlist->data[i] = sqlist->data[i + 1];
	sqlist->length -= 1;												//線性表長度減1
	return OK;
}
5. 順序表的更改
/*
method:
	順序表的更改
param:
	sqlist	要操作的順序表
	pos		要修改的位置
	num		要修改的值
*/

int Alter_Elem(Sqlist* sqlist, int pos, int num)
{
	if (pos<0 || pos >sqlist->length)									//判斷範圍
		return ERROR;
	sqlist->data[pos] = num;											//更改
	return OK;
}
(二)單鏈表的基本操作
1. 單鏈表的結構體
typedef struct LNODE
{
	int data;						//數據域
	struct LNODE* next;				//指針域
}LNODE;
2. 尾插法創建單鏈表
/*
method:
	尾插法創建單鏈表
param:
	lnode	要操作的順序表
	dat		數組中存放要創建鏈表的數據
	n		要創建單鏈表的長度
*/
int Create_Lnode_Tail(LNODE* lnode, int dat[], int n)
{
	LNODE* p, * q;
	int i = 0;
	//lnode = (LNODE*)__vcrt_malloc_normal(sizeof(LNODE));		//創造頭節點
	lnode->data = NULL;											//初始化頭節點
	lnode->next = NULL;								
	p = lnode;
	for (i; i < n; i++)
	{
		q = (LNODE*)__vcrt_malloc_normal(sizeof(LNODE));		//創建新結點
		q->data = dat[i];										//接收數組元素
		p->next= q;												//尾插法核心
		p = p->next;
	}
	p->next = NULL;												//表尾
	Show_Lnode_data(lnode);										//遍歷單鏈表元素
	return OK;
}
3. 頭插法創建單鏈表
/*
method:
	頭插法創建單鏈表
param:
	lnode	要操作的順序表
	dat		數組中存放要創建鏈表的數據
	n		要創建單鏈表的長度
*/
int Create_Lnode_Head(LNODE* lnode, int dat[], int n)
{
	int i = 0;
	LNODE* q;
	//lnode = (LNODE *)malloc(sizeof(LNODE));					//給lnode指針分配內存空間
	lnode->data = NULL;											//初始化頭結點
	lnode->next = NULL;
	for (i; i < n; i++)
	{
		q = (LNODE*)malloc(sizeof(LNODE));						//創建新結點
		q->data = dat[i];										//接收數組元素
		q->next = lnode->next;									//頭插法的核心
		lnode->next = q;
	}
	Show_Lnode_data(lnode);

	return OK;
}
4. 遍歷單鏈表
/*
method:
	遍歷單鏈表的數據
param:
	lnode	要操作的順序表
*/
void Show_Lnode_data(LNODE* lnode)
{
	LNODE* p = lnode;											//p指向單鏈表的頭結點
	printf("%p", lnode);										//打印出來頭結點指針的地址
	while (p->next != NULL)										//判斷下一個結點是否爲空
	{
		printf("->%d", p->next->data);							//打印出來鏈表中的數據
		p = p->next;											//遍歷單鏈表
	}
	printf("\n");							
}
5. 合併兩個單鏈表
/*
method:
	遍歷單鏈表的數據
param:
	A	要操作的順序表
	B	要操作的順序表
	C	存放合併後的單鏈表
*/
void Merge_Lnode(LNODE* A, LNODE* B, LNODE** C)					//這裏取指針的指針
{
	LNODE* a = A->next, * b =B->next, * c ;	
	*C = A;														//將A的存儲空間的地址給*C
	(*C)->next = NULL;											
	__vcrt_free_normal(B);										//釋放掉B的所佔的存儲空間
	c = *C;														//指針c指向頭結點C
	while (a != NULL && b != NULL)								//判斷這兩個結點大小
	{
		if (a->data > b->data)
		{
			c->next = b;										//鏈接單鏈表
			b = b->next;										//取下一個結點
			c = c->next;										//始終表示最後一個結點的存儲空間
		}
		else
		{
			c->next = a;										//鏈接單鏈表
			a = a->next;										//取下一個結點
			c = c->next;										//始終表示最後一個結點的存儲空間
		}
	}
	if (a != NULL)			c->next = a;						//若鏈表a還有值,則直接填補到末尾
	if (b != NULL)			c->next = b;						//若鏈表b還有值,則直接填補到末尾	
}
(三)雙鏈表的基本操作
1. 雙鏈表結構體
typedef struct DLNODE
{
	int data;							//存放結點中的數據
	struct DLNODE *prior;				//指向前驅結點的指針
	struct DLNODE* next;				//指向後繼結點的指針
}DLNODE;
2. 雙鏈表初始化
/*
method:
	創建雙鏈表
param:
	dlnode	要操作的順序表
	dat		數組中存放要創建鏈表的數據
	n		要創建單鏈表的長度
*/
int Create_DLnode(DLNODE** dlnode, int dat[], int n)
{
	int i = 0;
	DLNODE* p,* q;
	*dlnode = (DLNODE*)malloc(sizeof(DLNODE));				//爲dlnode分配內存空間
	(*dlnode)->data = NULL;									//初始化頭結點
	(*dlnode)->next = NULL;	
	(*dlnode)->prior = NULL;
	p = (*dlnode);											//p指針指向頭結點
	for (int i = 0; i < n; i++)
	{
		q = (DLNODE*)malloc(sizeof(DLNODE));
		q->data = dat[i];
		p->next = q;
		q->prior = p;
		p = q;
	}
	p->next = NULL;											//表尾
	return OK;
}
3. 雙鏈表的查詢
/*
method:
	查詢雙鏈表數據
param:
	dlnode	要操作的順序表
	x		要查找的元素值
return
	返回查找到的該結點
*/
DLNODE* Find_DLnode(DLNODE* dlnode, int x)
{
	DLNODE* p;
	p = dlnode->next;										//這裏p指針指向第一個結點
	while (p != NULL)										//判斷是否循環完鏈表
	{
		if (p->data == x)									//如果該結點正是所查找數據,直接break,返回該結點
			return p;
		p = p->next;
	}
	return NULL;
	
}
4. 雙鏈表的插入
/*
method:
	向雙鏈表插入數據
param:
	dlnode	要操作的順序表
	x		要插入的元素值
*/

int Insert_DLnode(DLNODE* dlnode, int x)
{
	DLNODE* p, * q;
	p = dlnode->next;										//p指針指向第一個結點
	q = (DLNODE*)malloc(sizeof(DLNODE));					//創建一個結點,以供插入
	q->data = x;
	q->next = NULL;
	q->prior = NULL;
	while (p != NULL)										//循環鏈表
	{	
		if (p->data < q->data)								//按照升序進行插入
		{
			if (p->next == NULL)							//如果這裏爲空,則鏈表循環完,直接將該結點插入到鏈表最後方
			{ 
				p->next = q;
				q->prior = p;
				break;
			}
			else
				p = p->next;								//p指向下一個元素
		}
		else
		{													//先假想一下,一鏈表從中間切開一刀
			q->prior = p->prior;							//先將要插入的結點兩端賦值。即:先將q的前驅,後繼進行賦值
			q->next = p;
			p->prior = q;									//然後再將被斷開的結點的兩端進行賦值。即p的前驅,q的前驅的後繼
			q->prior->next = q;
			break;
		}
	}
	return OK;
}
5. 雙鏈表的刪除
/*
method:
	向雙鏈表刪除數據
param:
	dlnode	要操作的順序表
	x		要刪除的元素值
*/

int Delete_DLnode(DLNODE* dlnode, int x)
{
	DLNODE* p;												
	p = dlnode->next;										//p指針指向第一個結點
	while (p != NULL)										//循環鏈表
	{
		if (p->data == x)									//如果找到要刪除的結點
		{													//假象一下,一鏈表從中間切開一刀,將中間取出一個結點p
			p->next->prior = p->prior;						//然後將斷開的兩端的鏈表的前驅和後繼進行賦值,這裏指的是 p的後繼的前驅,
			p->prior->next = p->next;						//和 p的前驅的後繼進行賦值
			__vcrt_free_normal(p);
			return OK;
		}
		p = p->next;
	}
	return ERROR;
}
6. 雙鏈表的遍歷
/*
method:
		遍歷雙鏈表的數據
param:
	dlnode	要操作的順序表
*/
void Show_DLnode_data(DLNODE* dlnode)
{
	DLNODE* p = dlnode;											//p指向單鏈表的頭結點
	printf("%p", dlnode);										//打印出來頭結點指針的地址
	while (p->next != NULL)										//判斷下一個結點是否爲空
	{
		printf("->%d", p->next->data);							//打印出來鏈表中的數據
		p = p->next;											//遍歷單鏈表
	}
	printf("\n");
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章