学习目标:
线性表
学习内容:
双链表的基本操作(查找,插入,删除);
数据结构线性表大题;
学习时间:
2021.3.31 12:00-1:00
学习产出:
尾插法建立双链表:
void createDlistR(DLNode *& L, int a[], int n)
{
DLNode* s, * r;
int i;
L = (DLNode*)malloc(sizeof(DLNode));
L->prior = NULL;
L->next = NULL;
r = L;
for (i = 0; i < n; ++i)
{
s = (DLNode*)malloc(sizeof(DLNode));
s->data = a[i];
r->next = s;
s->prior = r;
r = s;
}
r->next = NULL;
}
插入结点的代码:
s->next=p->next;
s->prior=p;
*p->next=s;
s->next->prior=p;
删除结点的算法:
q=p->next;
p->next=q->next;
q->next->prior=p;
free(p);
*/
逆置问题 :
给定一个线性表,如何将其中的元素逆置?
思路:可设置两个整型变量i和j,i指向第一个元素, j指向最后一个元素,边交换i和j所指元素,边让i和j相向而行,直到相遇。
//k=n/2 or k=(n-1)/2
for (int i = left, int j = right; i < j; ++i, --j)//两者相向
{
tempsum = a[i];
a[i] = a[j];
a[j] = tempsum;//交换两个元素
}
延伸(1):将一长度为n的数组的前端k(k<n)个元素逆序后移动到数组后端,要求原数组中数据不丢失,其余元素的位置无关紧要。
思路将上述循环的条件发生改变即可。
void reverse(int a[], int left, int right, int k)
{
int tempsum;
for (int i = left, int j = right; i < left + k && i < j; ++i, --j)
{
tempsum = a[i];
a[i] = a[j];
a[j] = tempsum;
}
}
延伸(2):将一长度为 n的数组的前端k(k<n)个元素保持原序移动到数组后端,要求原数组中数据不丢先,其余元素的位置无关紧要
**思路:**先将前端数据逆置,再逆置两端。
void moveToEnd(int a[], int n, int k)
{
revetse(a, 0, k - 1, k);
revetse(a, 0, n - 1, k);
}
延伸(3):将数组中的元素(X[0], X[1], … X[n-1]), 经过移动后变为(X[p], X[p+1], … X[n-1], X[0], X[1]…,X[p-1]),即循环左移p(0<p<n)个位置。
思路:先将两端分别逆置,再逆置两端。
void moveP(int a[], int n, int p)
{
revetse(a, 0, n - 1, p);
revetse(a, p, n - 1, n-p);
revetse(a, 0, n - 1, n);
}
例题1:
设顺序表用数组A[]表示,表中元素存储在数组下标0~m+n-1的范围内,前m个元素递增有序,后n个元素也递增有序,设计一个算法,使得整个顺序 表有序。
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++语言描述算法,并在关键之处给出注释。
**思路:**将m和n看成两个表 ,将一个人表拆分成若干元素填入另外一个表中。
void insertElem(int A[], int m, int n)
{
int i, j;
int tempsum;//用于辅助变量的暂存和交换+
for (i = m; i < m + n; ++i)//将[m,...,m+n-1]插入到[o,...,m-1]
{
tempsum = A[];
for (j = i - 1; j >= 0 && tempsum < A[j]; --j)
{
A[j + 1] = A[j]; //元素后移一位
A[j + 1] = tempsum;
}
}
}
例题2:
己知递增有序的单链表A、B (A、B中元素个数分别为m、n,且A、B都带有头结点)分别储存了一个集合,请设计算法,以求出两个集合A和B的差集A-B (仅由在A中出现而不在B中出现的元素所构成的集合)。将差集保存在单链表A中,并保持元素的递增有序性。
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++语言描述算法,并在关键之处给出注释。
(3)说明你所设计的算法的时间复杂度。
思路:在A中删除共有元素即可
void difference(LNode* A, LNode* B)
{
LNode* p = A->next, * q = B->next; //设置两指针分别指向A B
LNode* pre = A; //pre为指向p的前驱指针
LNode* r;
while(p!=NULL&&q!=NULL)
{
if (p->data < q->data)
{
pre = p;
p = p->next; //指针依次后移
}
else if (p->data > q->data)
{
q = q->next;
}
else //二者相同,开始删除
{
pre->next = p->next;
r = p;
p = p ->next;
free(r); //释放结点空间
}
}
}
(3):时间复杂度:O(m+n)。
参考书目
《2022数据结构高分笔记》 ——率辉