#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct ElementData
{
int index;
} Item ;
typedef struct node
{
Item item;
struct node * nextNode;
} Node;
typedef Node * linkList ;
Node * CreateInsertNode(Item *item) ;
/*链表初始化 */
bool initList(linkList *plist)
{
*plist = (linkList)malloc(sizeof(Node));
if(*plist == NULL)
{
return false;
}
(*plist)->nextNode = NULL;
return true;
}
/*返回链表长度 */
int getListLength(linkList *plist)
{
int length = 0;
Node * node = (*plist)->nextNode;
while(node != NULL)
{
length ++;
node = node->nextNode;
}
return length;
}
/*返回在链表L中第一个与Item相同的元素的位序, 没有返回为0 */
//两个结构体不能用 == 直接进行比较
int locateElem(linkList L, int item)
{
int index = 0;
while(L)
{
index ++;
if(L->nextNode->item.index == item)
{
return index;
}
L = L->nextNode;
}
return index;
}
/*返回在链表L的index-1个位置的元素 */
//ndex-1个位置避免在index个位置插入的时候出错
Node * getNode(linkList *L, int index)
{
linkList p = (*L);
int j = 1;
while(p != NULL && j < index)
{
p = p->nextNode;
j++;
}
if(p == NULL || j > index)
{
fprintf(stderr, "要找的元素位置超出链表的长度.\n");
exit(EXIT_FAILURE);
}
return p;
}
/*在链表L的index个位置插入item */
void listInsert(linkList *L, int index, Item *item)
{
//得到index-1的元素
linkList currentNode;
currentNode = getNode(L, index);
//创建要插入的元素
linkList insertNode = CreateInsertNode(item) ;
//插入到链表中
insertNode->nextNode = currentNode->nextNode;
currentNode->nextNode = insertNode;
}
/*把位于链表L的index个位置的元素删掉, 并用item返回其值 */
void listDelect(linkList *L, int index, Item *item)
{
//得到index-1的元素
linkList currentNode = getNode(L, index);
//删掉元素
linkList delectNode = currentNode->nextNode;
currentNode->nextNode = delectNode->nextNode;
*item = delectNode->item;
free(delectNode);
}
/*头插入 */
void CreateListHead(linkList *L, Item *item)
{
//创建要插入的元素并初始化
Node *insertNode = CreateInsertNode(item) ;
//插入
linkList head = *L;
insertNode->nextNode = head->nextNode;
head->nextNode = insertNode;
}
/*尾插入 */
void CreateListTail(linkList *L, Item *item)
{
//创建初始化要插入的元素
linkList insertNode = CreateInsertNode(item) ;
//找到最后一个元素
linkList list = (*L)->nextNode;
while(list->nextNode != NULL)
{
list = list->nextNode;
}
//插入
list->nextNode = insertNode;
}
/*删除 */
void ClearList(linkList *L)
{
linkList list = (*L)->nextNode ;
linkList p ;
while( list != NULL )
{
p = list->nextNode;
free(list);
list = p;
}
(*L)->nextNode = NULL;
}
/*输出链表 */
void listTraverse(linkList *L)
{
linkList p = (*L)->nextNode;
while(p)
{
printf("%d ,",p->item.index);
p = p->nextNode;
}
}
/*创建要插入的元素 返回创建的node指针 */
Node * CreateInsertNode(Item *item)
{
Node * insertNode = (linkList)malloc(sizeof(Node));
if(insertNode == NULL)
{
fprintf(stderr,"尾插入错误");
exit(EXIT_FAILURE);
}
insertNode->item = *item ;
insertNode->nextNode = NULL;
return insertNode;
}
/*单链表翻转/逆序 */
//current始终保持在第一位,pnext与prev遍历并完成交换。
void ListReverse(linkList *L)
{
linkList current; //当前节点
linkList next; //下一节点
linkList prev; //上一节点
current = (*L)->nextNode;
next = current->nextNode;
current->nextNode = NULL;
while(next){
prev = next->nextNode;
next->nextNode = current;
current = next;
next = prev;
}
(*L)->nextNode = current;
}
/*单链表翻转/逆序 */
//current始终是原链表的第一个数,然后把pnext不断移动到首位。
void ListReverse1(linkList *L)
{
linkList current; //当前节点
linkList next; //下一节点
current = (*L)->nextNode;
while(current->nextNode != NULL){
next = current->nextNode;
current->nextNode = next->nextNode;
next->nextNode = (*L)->nextNode;
(*L)->nextNode = next;
}
}
/*单链表翻转/逆序 */
//重新建立一个单链表newList,每次将L中的第一个结点放到newList后面
linkList ListReverse2(linkList *L)
{
linkList newlist = CreateInsertNode( &((*L)->item) );
if( (*L)->nextNode == NULL)
{
return NULL;
}
linkList firstNode;
while( (*L)->nextNode )
{
firstNode = newlist->nextNode;
newlist->nextNode = (*L)->nextNode;
(*L)->nextNode = (*L)->nextNode->nextNode;
newlist->nextNode->nextNode = firstNode;
}
free(*L);
return newlist;
}
// 获取单链表倒数第N个结点值
//建立两个指针,第一个先走n步,然后第2个指针也开始走,
//两个指针步伐(前进速度)一致。当第一个结点走到链表末尾时,
//第二个节点的位置就是我们需要的倒数第n个节点的值。
void GetNthNodeFromBack(linkList *L, int n, Item *item)
{
linkList list = (*L)->nextNode;
linkList last = (*L)->nextNode;
int index = 1;
while(list->nextNode != NULL && index < n)
{
index++;
list = list->nextNode;
}
if(list->nextNode == NULL || index > n)
{
fprintf(stderr, "要找的元素位置超出链表的长度.\n");
exit(EXIT_FAILURE);
}
while(list->nextNode != NULL)
{
list = list->nextNode;
last = last->nextNode;
}
*item = last->item;
}
//找到链表的中间节点
void GetMidNode(linkList *L, Item *e)
{
linkList first = *L;
linkList second = *L;
//first移动的速度是second的2倍
while(first->nextNode){
if(first->nextNode->nextNode){
first = first->nextNode->nextNode;
second = second->nextNode;
}else{
first = first->nextNode;
}
}
*e = second->item;
}
//删除重复的节点
void RemoveDupNode(linkList *L)
{
linkList first = *L; //用于遍历链表
linkList second ;
linkList delNode ;
while(first->nextNode){
second = first->nextNode; //从first后面开始遍历
while(second->nextNode){
//判断节点是否相等
if(second->nextNode->item.index == first->nextNode->item.index){
//删除节点
delNode = second->nextNode;
second->nextNode = delNode->nextNode;
free(delNode);
}else{
second = second->nextNode;
}
}
first = first->nextNode;
}
}
//在单链表第n个位置建环
//找到环入口点first,把最后的指针curr指向first
void BulidListLoop(linkList *L, int num)
{
linkList first = *L;
linkList curr ;
if(!first || num < 0){
fprintf(stderr,"建环失败.");
exit(EXIT_FAILURE);
}
for(int i = 0; i < num; i++){
if(!first){
fprintf(stderr,"建环失败,超出链表长度.");
exit(EXIT_FAILURE);
}
first = first->nextNode;
}
curr = first;
while(curr->nextNode){
curr = curr->nextNode;
}
curr->nextNode = first;
}
//判断链表是否有环
//设两个工作指针,一个快一个慢,如果有环的话,它们会必然在某点相遇。
int hasLoop(linkList *L)
{
linkList first = *L;
linkList second = *L;
while(first && second && second->nextNode){
first = first->nextNode;
if(second->nextNode){
second = second->nextNode->nextNode;
}
if(first == second){
return 1;
}
}
return 0;
}
//判断链表是否有环
//设两个工作指针p、q,p总是向前走,但q每次都从头开始走,
//对于每个节点,看p走的步数是否和q一样
int hasLoop1(linkList *L)
{
linkList first = *L;
int setp = 0;
while(first){
setp ++;
linkList second = *L;
int index = 0;
while(second){
index ++;
if(first == second){
if(setp == index){ //步数相等说明没环
break;
}else{
return 1;
}
}
second = second->nextNode;
}
first = first->nextNode;
}
return 0;
}
/*测试 */
int main(void)
{
linkList L;
if(!initList(&L))
{
fprintf(stderr,"初始化错误");
exit(EXIT_FAILURE);
}
Item item1 = {
item1.index = 5
};
Item item2 = {
item2.index = 6
};
Item item3 = {
item3.index = 7
};
Item item4 = {
item4.index = 6
};
Item item5 = {
item5.index = 9
};
Item item6 = {
item6.index = 4
};
listInsert(&L,1,&item1);
listInsert(&L,2,&item2);
listInsert(&L,3,&item3);
listInsert(&L,4,&item4);
CreateListHead(&L, &item5);
CreateListTail(&L, &item6);
int length = getListLength(&L);
// printf("length=%d\n",length);
listTraverse(&L); //显示
/*
printf("\n");
linkList n = ListReverse2(&L); //翻转
listTraverse(&n); //显示
Item item5;
listDelect(&L,1,&item5);
int length1 = getListLength(&L);
printf("length1=%d\n",length1);
listTraverse(&L);
*/
Node * getnode ;
getnode = getNode(&L, 2);
printf("\n%d\n", getnode->nextNode->item.index);
/*
Item i;
GetNthNodeFromBack(&L, 2,&i) ; 测试单链表倒数第N个结点值
printf("\n");
printf("%i",i.index);
*/
/*
Item i;
GetMidNode(&L, &i); 测试中间节点
printf("\n");
printf("%i",i.index);
*/
/*
RemoveDupNode(&L); 测试删除重复节点
printf("\n");
listTraverse(&L);
*/
/*
BulidListLoop(&L,2);
int i = hasLoop1(&L); 测试建环 检测是否有环
printf("\n%d",i) ;
*/
// int index = locateElem(L,5);
// printf("%d",index);
ClearList(&L);
return 0;
}
简单的单链表(2)
最新推荐文章于 2022-10-31 22:08:16 发布