王道数据结构伪代码实现——第二章 线性表

2.1 顺序表

2.1.1 顺序表的定义

#define MaxSize 50
typedef int ElemType;//顺序表中的元素类型

//静态分配
typedef struct {
	ElemType data[MaxSize];
	int length;//顺序表的当前长度
}Sqlist;

2.1.2 顺序表的插入

  • 移动元素
  • 插入元素
  • 增加表长
bool  ListInsert(Sqlist& L, int i, ElemType e) {
	if (i<1 || i>L.length + 1) {
		return false;
	}
	if (L.length >= MaxSize) {
		return false;
	}//判断插入是否合法
	for (int j = L.length; j >= i; j--) {//插入时,考虑j的初值,因为插入时要从最后一个元素开始依次后移一位,所以游标从j=L.length开始往前移动
		L.data[j] = L.data[j - 1];//考虑边界条件,当i=1时,j=1,最后将data[0]赋给data[1]便完成了所有元素的移动,所以j最小为1
		
	}
	L.data[i - 1] = e;//i为位序,在第i个位置上插入元素e,实际对应在数组中就是L.data[i-1]=e
	L.length++;//元素个数+1
	return true;
}

2.1.3 顺序表的删除

  • 删除元素
  • 移动元素
  • 删减表长
bool ListDelete(Sqlist& L, int i, ElemType& e) {
	if (i<1 || i>L.length) {
		return false;
	}
	if (L.length == 0) {
		return false;
	}
	e = L.data[i - 1];
	for (int j = i; j < L.length; j++) {//删除时,考虑j的初值,因为删除时元素要从被删除的结点开始依次前移一位,所以j=i,游标从前往后移动
		L.data[j - 1] = L.data[j];//考虑边界条件,j最大为L.length-1,即将最后一个位序的元素L.data[j]赋给L.data[j-1]
	}
	L.length--;
	return true;

2.1.4 查找元素

  • 按值查找:
int LocateElem(Sqlist L, ElemType e) {
	for (int i = 0; i < L.length; i++) {
		if (L.data[i] == e) {
			return i + 1;
		}
	}
	return 0;
}

  • 按位序查找:
ElemType GetElem(Sqlist L, int i){
	return L.data[i];

2.1.5 打印顺序表

void PrintList(Sqlist& L) {
	for (int i = 0; i < L.length; i++) {
		printf("%3d", L.data[i]);
	}
	printf("\n");
}

2.2 线性表的链式存储——单链表

2.2.1 单链表的定义

#define MaxSize 50

typedef struct LNode {
	int data;
	struct LNode* next;
}LNode, * LinkList;	

2.2.2 建立单链表

  • 头插法:每次插入的新结点都在头结点之后,因而是逆序
//头插法建立单链表 (逆向建立)
LinkList List_HeadInsert(LinkList& L) {
	LNode* s;//每次使s指向新结点
	int x;
	L = (LinkList)malloc(sizeof(LNode));//创建头结点 为什么L是一个指针 因为LinkList& L定义了结构体指针
	L->next = NULL;//初始化为空链表
	scanf("%d", &x);
	while (x != 9999) {
		s == (LNode*)malloc(sizeof(LNode));//创建新结点 s为 (LNode*)型指针 (强制类型转换)
		s->data = x;//新结点中存元素
		s->next = L->next;
		L->next = s;//新结点完全插入表中
		scanf("%d", &x);
	}
	return L;
}
  • 尾插法:每次插入的新结点都在尾结点之后,因而是正序
//尾插法建立单链表(正向建立)
LinkList List_TailInsert(LinkList& L) {
	int x;
	L = (LinkList)malloc(sizeof(LNode));
	LNode* s, * r = L;//每次使s指向新结点,r为表尾指针,且尾指针要初始化指向头结点 (或写成LinkLinst s,r也可以)
	scanf("%d", &x);
	while (x != 9999) {
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		r->next = s;
		r = s;//r每次都要指向新的表尾结点
		scanf("%d", &x);
	}
	r->next = NULL;//尾结点指针置空 很重要!
	return L;
}

2.2.3 查找元素

  • 按值查找
//按值查找结点值
LNode* LocateElem(LinkList L, int e) {
	LNode* p = L->next;
	while (p && p->data != e) {
		p = p->next;//指针后移
	}
	return p;
}

  • 按序号查找
//按序号查找结点值
LNode* GetElem(LinkList L, int i) {
	int j = 1;
	LNode* p = L->next;//j=1也就是位序为1时 对应的就是头指针
	if (0 == i) {
		return L;
	}
	if (i < 1) {
		return NULL;
	}
	while (p && j < i) {
		p = p->next;
		j++;//指针每次后移 直到找到位序为i时对应的指针
	}
	return p;
}

2.2.4 头插法第元素e插入第i个位置

bool List_HeadInsert(LinkList L, int i,int e) {
	LNode* p = GetElem(L, i-1);//先找到要插入位置的前驱节点
	if (NULL == p) {
		return false;
	}
	LNode* s = (LinkList)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

2.2.5 删除第i个元素

bool ListDelete(LinkList L, int i) {
	LNode* p = GetElem(L, i - 1);
	if (NULL == p) {
		return false;
	}
	LNode* q = p->next;//让q指向待删除元素
	p->next = q->next;//断链
	free(q);
	return true;
}

2.2.6 打印单链表

求表长原理相同,遍历链表并设置一个length计数即可:

void PrintList(LinkList L) {
	L = L->next;
	while (L != NULL) {
		printf("%3d", L->data);
		L = L->next;
	}
	printf("\n");
}

2.3 双链表

2.3.1 双链表的定义

typedef struct DNode{
	int data;
	struct DNode* prior, * next;
}DNode, * DLinkList;

2.3.2 双链表的建立

  • 头插法
//头插法建立双链表
DLinkList Dlist_head_insert(DLinkList& DL) {
	DNode* s;
	int x;
	DL = (DLinkList)malloc(sizeof(DNode));
	DL->next = NULL;
	DL->prior = NULL;//初始化双链表头结点
	scanf("%d", &x);
	while (x != 9999) {
		s= (DLinkList)malloc(sizeof(DNode));
		s->data = x;

		s->next = DL->next;
		if (DL->next != NULL) {
			DL->next->prior = s;
		}
		s->prior = DL;
		DL->next = s;
		scanf("%d", &x);
	}
	return DL;
}
  • 尾插法
//尾插法建立双链表
DLinkList Dlist_tail_insert(DLinkList& DL) {
	int x;
	DL = (DLinkList)malloc(sizeof(DNode));//带头节点的链表
	DNode* s, * r = DL;//r代表尾指针
	DL->prior = NULL;
	scanf("%d", &x);
	while (x != 9999) {
		s = (DNode*)malloc(sizeof(DNode));
		s->data = x;
		r->next = s;
		s->prior = r;
		r = s;
		scanf("%d", &x);
	}
	r->next = NULL;
	return DL;
}

2.3.3 按序号查找结点值

单/双链表查找结点,思路相同,都是设置指针和游标不断后移

//按序号查找结点值
DNode* GetElem(DLinkList DL, int i) {
	int j = 1;
	DNode* p = DL->next;
	if (i == 0) {
		return DL;
	}
	if (i < 1) {
		return NULL;
	}
	while (p&&j<i) {
		p = p->next;
		j++;
	}
	return p;
}

2.3.4 新结点插入双链表第i个位置

//新结点插入双链表第i个位置
bool DListFrontInsert(DLinkList DL, int i, int e) {
	DNode* p = GetElem(DL, i - 1);//查找要插入元素的前一个结点
	if (NULL == p) {
		return false;
	}
	DNode* s = (DLinkList)malloc(sizeof(DNode));
	s->data = e;
	//插入结点的关键四步
	s->next = p->next;
	p->next->prior = s;//要插入第i个位置,所以理解为默认第i个位置是有元素的,则无需考虑if (p.next != NULL)才要p->next->prior = s 的情况
	s->prior = p;
	p->next = s;
	return true;
}

2.3.5 删除第i个结点

//删除第i个结点
bool DListDelete(DLinkList DL, int i) {
	DNode* p = GetElem(DL, i - 1);//查找要删除元素的前一个结点
	if (NULL == p)
	{
		return false;
	}
	DNode* q = p->next;
	if (NULL == q)//删除的元素不存在
		return false;
	p->next = q->next;
	if (q->next != NULL) {//删除时考虑是否是最后一个结点 当其不是最后一个结点时 q->next->prior = p才有意义
		q->next->prior = p;
	}
	free(q);
	return true;
}

2.3.6 打印双链表

void PrintDList(DLinkList DL)
{
	DL = DL->next;
	while (DL != NULL) {
		printf("%3d", DL->data);
		DL = DL->next;
	}
	printf("\n");
}
  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值