数据结构学习---链表

封装链表

原来的单链表添加效率低,非法下标的判断效率也很低

1、单链表

    节点:
        数据域
        指针域
    链表结构数据项:
        头指针
        尾指针
        节点数量
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

//	设计节点
typedef struct Node
{
	TYPE data;
	struct Node* next;
}Node;

//	创建节点
Node* create_node(TYPE data)
{
	Node* node = malloc(sizeof(Node));
	node->data = data;
	node->next = NULL;
	return node;
}

//	设计带头节点的单链表结构
typedef struct List
{
	Node* head;		//	头指针
	Node* tail;		//	尾指针
	size_t size;	//	节点数量
}List;

//	创建单链表结构
List* create_list(void)
{
	List* list = malloc(sizeof(List));
	list->head = create_node(0);
	list->tail = NULL;
	list->size = 0;
	return list;
}

//	头添加
void add_head_list(List* list,TYPE data)
{
	Node* node = create_node(data);
	if(0 == list->size)
	{
		list->head->next = node;
		list->tail = node;
	}
	else
	{
		node->next = list->head->next;
		list->head->next = node;
	}
	list->size++;
}

//	尾添加
void add_tail_list(List* list,TYPE data)
{
	Node* node = create_node(data);	
	if(0 == list->size)
	{
		list->head->next = node;
		list->tail = node;
	}
	else
	{
		list->tail->next = node;
		list->tail = node;
	}
	list->size++;
}

//	头删除
bool del_head_list(List* list)
{
	if(0 == list->size)	return false;
	Node* temp = list->head->next;
	list->head->next = temp->next;
	if(1 == list->size)	list->tail = NULL;
	free(temp);
	list->size--;
	return true;
}

//	尾删除
bool del_tail_list(List* list)
{
	if(0 == list->size)	return false;
	free(list->tail);//释放了使用权
	if(1 == list->size)
	{
		list->head->next = NULL;
		list->tail = NULL;
	}
	else
	{
		Node* prev = list->head->next;
		while(prev->next != list->tail) prev = prev->next; //空指针不能解引用,这里只是看一下地址
		prev->next = NULL;
		list->tail = prev;
	}
	list->size--;
	return true;
}

//	插入
bool insert_list(List* list,int index,TYPE data)
{
	if(0 >= index || index >= list->size)	return false;

	Node* node = create_node(data);
	Node* prev = list->head->next;
	for(int i=1; i<index; i++)
	{
		prev = prev->next;	
	}
	node->next = prev->next;
	prev->next = node;
	list->size++;
	return true;
}

//	按值删除
bool del_value_list(List* list,TYPE data)
{
	if(data == list->head->next->data) return del_head_list(list);	
	if(data == list->tail->data)	return del_tail_list(list);

	for(Node* n=list->head->next; n->next; n=n->next)
	{
		if(n->next->data == data)
		{
			Node* temp = n->next;
			n->next = temp->next;
			free(temp);
			list->size--;
			return true;
		}
	}
	return false;
}

//	按位置删除
bool del_index_list(List* list,int index)
{
	if(0 > index || index >= list->size)	return false;
	if(0 == index)	return del_head_list(list);
	if(index == list->size-1) return del_tail_list(list);

	Node* prev = list->head->next;
	for(int i=1; i<index; i++)
	{
		prev = prev->next;	
	}
	Node* temp = prev->next;
	prev->next = temp->next;
	free(temp);
	list->size--;
	return true;
}

//	按位置修改
bool modify_index_list(List* list,int index,TYPE data)
{
	if(0 > index || index >= list->size)	return false;
	Node* n = list->head->next;
	for(int i=0; i<index; i++)
	{
		n = n->next;	
	}
	n->data = data;
	return true;

}
//	按值修改 修改全部
bool modify_value_list(List* list,TYPE old,TYPE new)
{
	bool flag = false;
	for(Node* n=list->head->next; n; n=n->next)
	{
		if(n->data == old)
		{
			n->data = new;
			flag = true;
		}
	}
	return flag;
}

//	查询
int query_list(List* list,TYPE data)
{
	Node* n = list->head->next;
	for(int i=0; n; n=n->next,i++)
	{
		if(n->data == data)	return i;	
	}
	return -1;
}

//	排序
void sort_list(List* list)
{
	for(Node* n = list->head->next; n->next; n=n->next)
	{
		for(Node* m = n->next; m; m=m->next)
		{
			if(n->data > m->data)
			{
				TYPE temp = n->data;
				n->data = m->data;
				m->data = temp;
			}
		}
	}
}

//	访问
bool access_list(List* list,int index,TYPE* val)
{
	if(0 > index || index >= list->size) return false;

	Node* n = list->head->next;
	while(index--) n=n->next;
	*val = n->data;
	return true;
}

//	清空
void clean_list(List* list)
{
//	while(list->size) del_head_list(list);
	
	Node* n = list->head->next;
	while(n)
	{
		Node* temp = n;
		n = temp->next;
		free(temp);
	}
	list->head->next = NULL;
	list->tail = NULL;
	list->size = 0;
}

//	销毁
void destory_list(List* list)
{
	clean_list(list);
	free(list->head);
	free(list);
}

//	遍历
void show_list(List* list)
{
	for(Node* n = list->head->next; n; n=n->next)
	{
		printf("%d ",n->data);	
	}
	printf("\n");
}

int main(int argc,const char* argv[])
{
	List* list = create_list();
	for(int i=0; i<10; i++)
	{
		add_tail_list(list,rand()%100);
	}
	show_list(list);

	//insert_list(list,10,100);
	//del_value_list(list,490);
	//del_index_list(list,1);
//	modify_index_list(list,9,100);
//	modify_value_list(list,77,999);
//	printf("index:%d\n",query_list(list,100));
//	sort_list(list);
	TYPE num = -100;
	access_list(list,10,&num);
	printf("num=%d\n",num);
	clean_list(list);
	show_list(list);
}

2、静态链表

    节点:
        数据域
        游标
    静态链表的节点存储在连续的内存,通过游标来访问下一个节点
    这种链表在插入、删除时只需要修改游标的值,而不用申请、释放内存从而达到链式结构的效果
    但是也牺牲了随机访问的功能,主要是给没有指针的编译实现的一种单链表效果

3、循环链表

    链表的最后一个节点的next不再指向NULL,而是指向头节点,这种链表叫做单向循环链表,
    简称循环链表,它的好处是可以通过任意节点遍历整个链表。

4、双向链表

    节点:
        前趋指针
        数据域
        后继指针
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

//	设计双向节点,不构建双向链表结构
typedef struct Node
{
	struct Node* prev;	//	前趋
	TYPE data;
	struct Node* next;	//	后继
}Node;

//	创建节点
Node* create_node(TYPE data)
{
	Node* node = malloc(sizeof(Node));
	node->prev = node;
	node->data =data;
	node->next =node;
	return node;
}

//	添加的依赖函数,在p节点与n节点中间插入新节点
void _add_list(Node* p,Node* n,TYPE data)
{
	Node* node = create_node(data);
	node->next = n;
	node->prev = p;
	p->next = node;
	n->prev = node;
}

//	头添加
void add_head_list(Node* head,TYPE data)
{
	_add_list(head,head->next,data);	//设计的是带头节点的双链表
}
//	尾添加
void add_tail_list(Node* head,TYPE data)
{
	_add_list(head->prev,head,data);
}

//	删除节点node
void _del_list(Node* node)
{
	Node* p = node->prev;
	Node* n = node->next;
	p->next = n;
	n->prev = p;
	free(node);
}

//	按位置删除
bool del_index_list(Node* head,size_t index)
{
	Node* n = head->next;
	for(int i=0; i<index; i++)
	{
		n = n->next;
		if(head == n) return false;
	}
	_del_list(n);
	return true;

}
//	按值删除
bool del_value_list(Node* head,TYPE data)
{
	for(Node* n=head->next; head != n; n=n->next)
	{
		if(n->data == data)	
		{
			_del_list(n);
			return true;
		}
	}
	return false;
}

//	遍历
void show_list(Node* head)
{
	for(Node* n = head->next; head != n; n=n->next)
	{
		printf("%d ",n->data);	
	}
	printf("\n");
}

int main(int argc,const char* argv[])
{
	Node* head = create_node(0);	//带头节点的双链表
	for(int i=0; i<10; i++)
	{
		add_head_list(head,i);	
	}
	show_list(head);
	del_index_list(head,2);
	del_value_list(head,9);
	show_list(head);
}

封装双向链表

 双向链表数据项:
        头节点
        节点数量
    双向链表的特点:
        1、从任意节点都可以遍历整个链表
        2、已知节点的位置,可以选择从前到后或者从后到前进行遍历查找,以此提高链表的访问效率 
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int
//	设计双向链表节点
typedef struct Node
{
	struct Node* prev;
	TYPE data;
	struct Node* next;
}Node;

//	创建节点
Node* create_node(TYPE data)
{
	Node* node = malloc(sizeof(Node));
	node->prev = node;
	node->data = data;
	node->next = node;
	return node;
}

//	设计双向链表结构
typedef struct DoubleList
{
	Node* head;		//带头节点
	size_t size;	
}DoubleList;

//	创建链表
DoubleList* create_list(void)
{
	DoubleList* list = malloc(sizeof(DoubleList));
	list->head = create_node(0);
	list->size = 0;
	return list;
}

//	在前驱q和后继n之间添加一个节点
//	下划线开头表示该函数是依赖函数
void _add_list(Node* p,Node* n,TYPE data)
{
	Node* node = create_node(data);
	node->prev = p;
	node->next = n;
	p->next = node;
	n->prev = node;
}

//	删除当前节点
void _del_list(Node* node)
{
	/*
	Node* p = node->prev;
	Node* n = node->next;
	p->next = n;
	n->prev = p;
	free(node);
	*/
	node->prev->next = node->next;
	node->next->prev = node->prev;
	free(node);
}

//	访问指定位置的节点
Node* _index_list(DoubleList* list,size_t index)
{
	if(list->size <= index) return NULL;
	if(index < list->size/2)
	{
		//	从前往后
		Node* n = list->head->next;
		while(index--) n = n->next;
		//printf("%d\n",n->data);
		return n;
	}
	else
	{
		//	从后往前
		Node* n =list->head->prev;
		while(++index < list->size) n = n->prev;
		//printf("%d\n",n->data);
		return n;
	}
}

//	访问指定数值的节点
Node* _value_list(DoubleList* list,TYPE data)
{
	for(Node* n=list->head->next; list->head!=n; n=n->next)
	{
		if(n->data == data)	return n;	
	}
	return NULL;
}

//	头添加
void add_head_list(DoubleList* list,TYPE data)
{
	_add_list(list->head,list->head->next,data);
	list->size++;
}

//	尾添加
void add_tail_list(DoubleList* list,TYPE data)
{
	_add_list(list->head->prev,list->head,data);
	list->size++;
}

//	插入
bool insert_list(DoubleList* list,size_t index,TYPE data)
{
	Node* node = _index_list(list,index);	
	if(NULL == node)	return false;

	_add_list(node->prev,node,data);
	list->size++;
	return true;
}

//	按位置修改
bool modify_index_list(DoubleList* list,size_t index,TYPE data)
{	
	Node* node = _index_list(list,index);
	if(NULL == node) return false;

	node->data = data;
	return true;
}

//	按值修改 更新
int modify_value_list(DoubleList* list,TYPE old,TYPE new)
{
	int cnt = 0;	//修改次数
	for(Node* n=list->head->next; n!=list->head; n=n->next)
	{
		if(n->data == old)
		{
			n->data = new;	
			cnt++;
		}
	}
	return cnt;
}

//	访问
bool access_list(DoubleList* list,size_t index,TYPE* data)
{
	Node* node = _index_list(list,index);
	if(NULL == node)	return false;

	*data = node->data;
	return true;
}

//	查询
int query_list(DoubleList* list,TYPE data)
{
	Node* n = list->head->next;
	for(int i=0; i<list->size; i++)
	{
		if(n->data == data) return i;
		n = n->next;
	}
	return -1;
}

//	按位置删除
bool del_index_list(DoubleList* list,size_t index)
{
	Node* node = _index_list(list,index);
	if(NULL == node)	return false;

	_del_list(node);
	list->size--;
	return true;
}

//	按值删除
bool del_value_list(DoubleList* list,TYPE data)
{
	Node* node = _value_list(list,data);
	if(NULL == node) return false;
	
	_del_list(node);
	list->size--;
	return true;
}

//	遍历
void show_list(DoubleList* list)
{
	for(Node* n=list->head->next; list->head!=n; n=n->next)
	{
		printf("%d ",n->data);	
	}
	printf("\n");
}

//	清空
void clean_list(DoubleList* list)//清空之后还能向结构体中添加新的节点
{
	Node* node = list->head->next;
	while(node != list->head)
	{
		Node* temp = node;
		node = node->next;
		free(temp);
	}
	list->head->next = list->head;
	list->head->prev = list->head;
	list->size = 0;
}

//	销毁
void destory_list(DoubleList* list)//这个结构体就无法使用了
{
	clean_list(list);
	free(list->head);
	free(list);
}

int main(int argc,const char* argv[])
{
	DoubleList* list = create_list();
	for(int i=0; i<10; i++)
	{
		add_tail_list(list,i);	
	}
	show_list(list);
	insert_list(list,0,100);
	insert_list(list,3,100);
	insert_list(list,6,100);
	show_list(list);
	modify_value_list(list,100,999);
	show_list(list);
	TYPE num = 0;
	access_list(list,12,&num);
	printf("num=%d\n",num);
	printf("index=%d\n",query_list(list,1));
	del_index_list(list,12);
	del_value_list(list,8);
	show_list(list);
	clean_list(list);
//	destory_list(list);
	printf("--------\n");
	for(int i=0; i<10; i++)
	{
		add_tail_list(list,i);	
	}
	show_list(list);

}

5、Linux内核链表

    链表的节点无法包含万物,那就让万物来包含链表的节点
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

//Linux内核链表

//	遍历
#define list_for_each(n,head) \
	for(n=head->next; n!=head; n=n->next)

//	计算结构体成员所处的结构中的地址编号
//	type 结构类型 mem结构成员名

#define offset(type,mem) ((int)(&((type*)0)->mem))

//	计算某结构成员所处的结构变量的首地址
//	node要计算的node type结构类型 mem结构成员名

#define node_to_obj(node,type,mem) \
	(type*)((void*)node-offset(type,mem)) //void为一个字节
//考点就是以上两个宏定义

//	第二种遍历方式
#define list_for_each_entry(obj,head,mem) \
	for(obj=node_to_obj(head->next,typeof(*obj),mem); \
		&obj->mem != head;\
		obj=node_to_obj(obj->mem.next,typeof(*obj),mem))

//	设计链表节点
typedef struct Node
{
	struct Node* prev;
	struct Node* next;
}Node;

//	创建链表
Node* create_list(void)
{
	Node* head = malloc(sizeof(Node));
	head->prev = head;
	head->next = head;
	return head;
}

void _add_list(Node* prev,Node* next,Node* node)
{
	next->prev = node;
	node->next = next;
	node->prev = prev;
	prev->next = node;
}

//	头添加
void add_head_list(Node* head,Node* node)
{
	_add_list(head,head->next,node);
}

//	尾添加
void add_tail_list(Node* head,Node* node)
{
	_add_list(head->prev,head,node);	
}

//	判断链表是否为空
bool empty_list(Node* head)
{
	return head->next == head;	
}

//	删除节点
void _del_list(Node* node)
{
	node->next->prev = node->prev;
	node->prev->next = node->next;
	node->next = NULL;
	node->prev = NULL;	//不可以free 节点
}

//	头删除
Node* del_head_list(Node* head)
{
	if(empty_list(head)) return NULL;
	Node* node = head->next;
	_del_list(node);
	return node;
}

//	尾删除
Node* del_tail_list(Node* head)
{
	if(empty_list(head)) return NULL;
	Node* node = head->prev;
	_del_list(node);
	return node;
}

//	按位置删除
Node* del_index_list(Node* head,size_t index)
{
	Node* node = head->next;
	for(int i=0; i<index; i++)
	{
		node = node->next;
		if(node == head) return NULL;
	}
	_del_list(node);
	return node;
}

/*----------以上都是通用的代码库,下面才是用户使用代码库的内容-------*/
typedef struct Student
{
	char age;
	int id;
	float score;
	Node node; //node是个节点,可以通过这个节点访问到下一个节点即next
	char sex;
	char name[20];
}Student;

int main(int argc,const char* argv[])
{
	Student* stu = malloc(sizeof(Student));
	printf("---%p %p---\n",stu,&stu->node);
	printf("---%p %p---\n",(Student*)0,&((Student*)0)->node);

	Node* head = create_list();
	for(int i=0; i<10; i++)
	{
		Student* stu = malloc(sizeof(Student));
		sprintf(stu->name,"hehe");
		stu->sex = i%2?'w':'m';
		stu->age = 20+i;
		stu->id = 1001+i;
		stu->score = rand()%100;
		add_tail_list(head,&stu->node);

		printf("%s %c %hhd %d %g\n",
			stu->name,stu->sex,stu->age,stu->id,stu->score);
	}

	printf("====================\n");
	del_index_list(head,3);
	del_tail_list(head);
	del_tail_list(head);

	//	测试第二种遍历方式
	Student* stu1 = NULL;
	list_for_each_entry(stu1,head,node)
	{	
		printf("%s %c %hhd %d %g\n",
			stu1->name,stu1->sex,stu1->age,stu1->id,stu1->score);
	}

	/*
	Node* n = NULL;
	list_for_each(n,head)
	{
	//	Student* stu = (Student*)n;
		Student* stu = node_to_obj(n,Student,node);
		printf("%s %c %hhd %d %g\n",
			stu->name,stu->sex,stu->age,stu->id,stu->score);
	}
	*/
}

6、通用链表

	节点:
		void* ptr;  
		指针域

	运算:常规功能+回调函数 


关于链表常考的笔试面试题:
1、单链表逆序 ,在原链表的基础上调整
2、找出链表中的倒数第n个节点
3、判断链表是否有环
4、找出环形链表的入口
5、合并两个有序链表,合并后依然保持有序
6、判断两个链表是否是Y型链表

通用链表头文件

#include <stdbool.h>

//类型重定义函数指针
typedef int (*Compar)(const void*,const void*); //Compar 相当于引用了 int (const void*,const vooid*)

//	链表节点
typedef struct Node
{
	void* ptr;	//数据域,void*可以转换成任何类型的指针,指针可以指向任何东西,比TYPE更全面
	struct Node* prev;
	struct Node* next;
}Node;

//	通用链表结构
typedef struct List
{
	Node* head;
	size_t size;
}List;

//	创建链表
List* create_list(void);

//	添加
void add_list(List* list,void* ptr);

//	插入
bool insert_list(List* list,size_t index,void* ptr);

//	删除 位置
bool del_index_list(List* list,size_t index);

//	删除 值
bool del_value_list(List* list,void* ptr,Compar cmp);
//	查询
void* qurey_list(List* list,void* ptr,Compar cmp);
//	访问
void* visit_list(List* list,size_t index);
//	排序
//	清空
void clean_list(List* list);
//	销毁
void destory_list(List* list);
//	遍历
void show_list(List* list,void (*show)(void* ));

#endif//LIST_H

list.c

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include "list.h"

//	创建节点
static Node* create_node(void* ptr)
{
	Node* node = malloc(sizeof(Node));
	node->ptr = ptr;
	node->prev = node;
	node->next = node;
	return node;
}

//	两个节点之间插入一个新节点
static void _add_list(Node* prev,Node* next,void* ptr)
{
	Node* node = create_node(ptr);
	prev->next = node;
	next->prev = node;
	node->prev = prev;
	node->next = next;
}

//删除节点
static void _del_list(Node* node)
{
	node->prev->next = node->next;
	node->next->prev = node->prev;
	free(node->ptr);
	free(node);
}

//根据位置访问节点
static Node* _visit_list(List* list,size_t index)
{
	if(index >= list->size) return NULL;
	if(index < list->size/2)
	{
		Node* node = list->head->next;
		while(index--) node = node->next;
		return node;
	}
	else
	{
		Node* node = list->head->prev;
		while(++index < list->size) node = node->prev;
		return node; 
	}
	
}

//	创建链表
List* create_list(void)
{
	List* list = malloc(sizeof(List));
	list->head = create_node(0);
	list->size = 0;
	return list;
}

//	添加 尾添加
void add_list(List* list,void* ptr)
{
	_add_list(list->head->prev,list->head,ptr);
	list->size++;
}

//	插入
bool insert_list(List* list,size_t index,void* ptr)
{
	Node* node = _visit_list(List* list, size_t index);
	if (NULL == node) return false;
	 _add_list(node->prev,node,ptr);
	return true;
}	

//	删除 位置
bool del_index_list(List* list,size_t index);
{
	Node* node = _visit_list(list,index);
	if(NULL == node) return false;
	_del_list(node);
	list->size--;
	return true;
}

//	删除 值
bool del_value_list(List* list,void* ptr,Compar cmp)//Compar是调用者需要提供的函数
{
	for(Node* n = list->head->next;n!=list->head;n=n->next)
	{
		if(0 == cmp(ptr,n->ptr))
		{
			_del_list(n);
			list->size--;
			return true;
		}
	}
	return false;
}
//	查询
void* qurey_list(List* list,void* ptr,Compar cmp)
{
	for(Node* n = list->head->next;n!=list->head;n=n->next)
	{
		if(0 == cmp(ptr,n->ptr))
			return n->ptr;
	}
	return NULL;
}

//	访问
void* visit_list(List* list,size_t index)
{
	Node* node = _visit_list(list,index);
	if(NULL == node) return NULL;
	return node->ptr;
}

//	排序
void sort_list(List* list,Compar cmp)
{
	for(Node* n = list->head->next;n->next!=list->head;n=n->next)
	{
		for(Node* m = n->next;m!=list->head;m=m->next)
		{
			if(-1 == cmp(N->ptr,m->ptr))
			{
				void* tmp = n->ptr;
				n->ptr = m->ptr;
				m->ptr = tmp;
			}
		}
	}
}

//	清空
void clean_list(List* list)
{
	Node* node = list->head->next;
	while(list->size)
	{
		Node* temp = node;
		node = node->next;
		free(temp->ptr);
		free(temp);
	}
	list->head->next = list->head;
	list->head->prev = list->head;
}
//	销毁
void destory_list(List* list)
{
	clean_list(list);
	free(list->head->ptr);
	free(list->head);
	free(list);
}

//	遍历
void show_list(List* list,void (*show)(void* ))
{
	for(Node* n=list->head->next; n!=list->head; n=n->next)
	{
		show(n->ptr);
	}
}

text.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "list.h"

//	此文件才是调用者写的代码

typedef struct Student
{
	char name[20];
	char sex;
	int id;
}Student;

	
//	打印结构体的回调函数由调用者提供
void show_stu(void* ptr)
{
	Student* stu = ptr;
	printf("姓名:%s 性别:%c 学号:%d\n",stu->name,stu->sex,stu->id);
}

//结构体比较函数也是由调用者提供的回调函数
int stucmp(const void* s1.const void* s2)
{
	const Student* stu1 = s1;
	const Student* stu2 = s2;
	if(stu1->id > stu2->id)
		return 1;
	if(stu1->id < stu2->id)
		return -1;
	return 0;
}

int main(int argc,const char* argv[])
{
	List* list = create_list();
	for(int i=0; i<10; i++)
	{
		Student* stu = malloc(sizeof(Student));
		strcpy(stu->name,"hehe");
		stu->sex = i%2?'w':'m';
		stu->id = 1001+i;
		add_list(list,stu);
	}
	show_list(list,show_stu);
	printf("----------------\n");
	Student stu = {"xixi",'w',1001);
	Student* stup;
	//del_value_list(list,&stu,stucmp);
	//insert_list(list,10,&stu);
	//del_value_list(list,0);
	show_stu(qurey_list(list,&stu,stucmp));
	sort_list(list,stucmp);
	//show_list(list,show_stu);

}
这些文档涵盖了5G网络优化的多个方面,包括**载波聚合、干扰管理、负载均衡、电调核查等**。以下是对这些文档内容的详细总结: #### **5G网络优化中的载波聚合技术** - **载波聚合的定义和作用**: - 载波聚合(CA)是3GPP在Release 10阶段引入的技术,通过将多个连续或非连续的载波聚合成更大的带宽,提高整网资源利用率和用户体验。 - **开启步骤及脚本**: - 确认站内是否有CA License。 - 添加CA组并配置相关参数。 - 基站盲配置开关打开,激活门限设置,增加CA小区集辅小区配置。 - **载波聚合A5测量事件开关的作用**: - A5测量事件开关打开时,支持CA的UE会A4转A5,调整A5门限1到-43dBm,类似于走A4事件触发异频切换。 - 关闭时,当UE处于载波聚合状态下才会将A4转A5,但不会调整A5门限1。 #### **干扰管理和优化** - **系统外干扰**: - 信号放大器和信号屏蔽器是主要的干扰源。解决建议包括协调推进信号放大器关、替、拆工作,引导用户使用VOLTE业务,以及联系公安进行收缴关闭信号屏蔽器。 - **系统内干扰**: - 包括杂散干扰、阻塞干扰和互调干扰。解决方法包括调整天面、增加隔离度,加装滤波器等。 #### **移动性负载均衡(MLB)配置方案** - **背景描述**:随着LTE用户数的快速发展,部分小区的用户数或PRB利用率已接近容量极限。MLB是指eNodeB判断小区的负载状态,当小区处于高负载状态时,将负载高小区中部分UE转移到负载低的小区,平衡异频或异系统之间的负载。 - **方案分析与实施**: - 方案介绍:MLB分为触发模式、选择目标小区、负载均衡执行三个阶段。根据这三个维度可划分为以下各种类型。 - 配置原则:确定候选邻区,交互负载信息,识别交互邻区和盲邻区,确定目标小区列表。 - 均衡执行:现网采用切换的方式转移同步态用户,RRC connection release方式转移空闲态用户。 - 三种均衡方式的优缺点对比:异频同步态用户数均衡(转移同步态用户)、异频同步态用户数均衡(转移空闲态用户)、异频空闲态UE预均衡。 #### **FDD电调核查及修改方法** - **FDD侧电调修改方法**:查询电调天线配置信息和子单元配置信息,可以查询/修改电子下倾角。 - **GSM侧电调修改方法**:查询天线设备编号、框槽号及天线设备序列号等信息。 - **常见的天线类型及匹配问题**:HW天线是现网绝大多数天线类型,需特别注意设备厂家编码和设备序列号的匹配问题。 综上所述,这些文档详细介绍了5G网络优化中的关键技术和方法,从载波聚合到干扰管理再到移动性负载均衡和FDD电调核查等方面提供了全面的指导和解决方案。通过这些内容的学习和应用,可以有效提升5G网络的性能和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值