C# deleting nodes in linkedlist - c#

I'm working on a radix sort algorithm with linked list. I have in mind how I'm going to solve it, but I need to be able to delete the whole linked list (deleting node one by one when looping through linked list). The problem which I encountered is my current (node) pointer doesn't get the value first. I have tried many different things, but I guess I don't grasp how to reset the pointers 'first', 'current', 'left', 'right' when deleting a node
Radixsort.cs:
public static void Counting_sort(LinkedList<int> list, int exp)
{
LinkedList<int> D = new LinkedList<int>();
LinkedList<int>[] lists = new LinkedList<int>[10];
for (int i = 0; i < lists.Length; i++)
{
lists[i] = new LinkedList<int>();
}
// Skaiciu daznumas
int number = 0;
for (list.Beginning(); list.Exists(); list.Next())
{
number = (list.Take() / exp % 10);
lists[number].Add(list.Take());
list.Remove(list.TakeNode()); <---------- Removing node one by one till it's empty
}
for (int i = 0; i < lists.Length; i++)
{
for (list.Beginning(); list.Exists(); list.Next())
{
//list.Add(lists)
}
}
}
public static void Radix_sort(LinkedList<NumberPlate> list)
{
LinkedList<int> intList = new LinkedList<int>();
AddIntToLinkedList(list, intList);
for (int exp = 1; exp < Math.Pow(10, 9); exp *= 10)
{
Counting_sort(intList, exp);
}
}
LinkedList.cs
public class LinkedList<T> : IEnumerable<T> where T : IComparable<T>, IEquatable<T>
{
public sealed class Node<T>
{
public Node<T> Right;
public Node<T> Left;
public T data;
public Node(T value, Node<T> left, Node<T> right)
{
Left = left;
Right = right;
data = value;
}
}
private Node<T> first;
private Node<T> last;
private Node<T> current;
public int size;
public LinkedList()
{
first = null;
last = null;
current = null;
size = 0;
}
public void Add(T element)
{
var node = new Node<T>(element, last, null);
if (first != null)
{
last.Right = node;
last = node;
}
else
{
first = node;
last = node;
}
current = node;
size++;
}
public void Remove(Node<T> node)
{
if (node == first)
{
first = first.Right;
}
else if (node == last)
{
last = last.Left;
}
else if (node.Left != null)
{
node.Left.Right = node.Right;
}
else if (node.Right != null)
{
node.Right.Left = node.Left;
}
size--;
}
public void Beginning()
{
current = first;
}
public void End()
{
current = last;
}
public void Next()
{
current = current.Right;
}
public void Previous()
{
current = current.Left;
}
public bool Exists()
{
return current != null;
}
public T Take()
{
return current.data;
}
public Node<T> TakeNode()
{
return current;
}

I think you should be able to do this to clear a list:
foreach (var node in list)
{
list.Remove(node);
}
The Remove method is already implemented for you on the LinkedList class, so you should make use of it.
Because the LinkedList implements IEnumerable, you can iterate over it using foreach.

Related

How to make loot table not repeat items in Unity?

I am looking to randomly generate 3 items using a loot table. The loot table currently works as expected, it will randomly generate an item based on the item's rarity. However, I don't want there to be duplicates of the same item. How can I set this up? This script is currently attached to 3 separate GameObject item pedestals.
using System.Collections.Generic;
using UnityEngine;
public class ShopItemSpawner : MonoBehaviour
{
[System.Serializable]
public class DropItem
{
public string name;
public GameObject item;
public int dropRarity;
}
public List<DropItem> ShopItemPool = new List<DropItem>();
private void Start()
{
int itemWeight = 0;
for (int i = 0; i < ShopItemPool.Count; i++)
{
itemWeight += ShopItemPool[i].dropRarity;
}
int randomValue = Random.Range(0, itemWeight);
for (int j = 0; j < ShopItemPool.Count; j++)
{
if (randomValue <= ShopItemPool[j].dropRarity)
{
Instantiate(ShopItemPool[j].item, transform.position, Quaternion.identity);
return;
}
randomValue -= ShopItemPool[j].dropRarity;
}
}
}
You could clone the ShopItemPool list and with each item rolled you remove that item from the list. You then need to go all over again by recalculating the total weight.
I find it useful to have a general purpose class for randomizing items with weights, it allows you do this this:
var randomizer = new WeightRandomizer<DropItem>();
foreach (var shopItem in ShopItemPool) {
randomizer.Add(shopItem, shopItem.dropRarity);
}
randomizer.Roll(); // Get a random element based on weight.
randomizer.Take(); // Get a random element based on weight and remove it from the randomizer.
General Purpose Weight Randomizer:
public class WeightRandomizer<T> {
[Serializable]
public class WeightedElement<T> {
public T value;
public int weight;
public WeightedElement (T value, int weight) {
this.value = value;
this.weight = weight;
}
}
private readonly List<WeightedElement<T>> elements = new();
public void Add (T value, int weight) => elements.Add(new WeightedElement<T>(value, weight));
public void AddRange (IEnumerable<WeightedElement<T>> weightedElements) => elements.AddRange(weightedElements);
public int TotalWeight() => elements.Sum(x => x.weight);
public T Roll() => Pick(false);
public T Take() => Pick(true);
private T Pick (bool remove) {
if (elements.Count == 0) {
Debug.LogWarning($"{nameof(WeightRandomizer<T>)} is missing elements.");
return default(T);
}
var roll = Random.Range(0, TotalWeight());
var selectedIndex = elements.Count - 1;
var selected = elements[selectedIndex].value;
for (var i = 0; i < elements.Count; i++) {
var element = elements[i];
// Found an element with a low enough value.
if (roll < element.weight) {
selected = element.value;
selectedIndex = i;
break;
}
// Keep searching for an element with a lower value.
roll -= element.weight;
}
// Sometimes we want to take and remove the element from the pool.
if (remove) elements.RemoveAt(selectedIndex);
return selected;
}
}

Radix sort in singly-linked list C#

I'm trying to do a Radix sort in a Linked list class. I found radix sort algorithm for array and am trying to change it to work with my linked list. However, I'm a bit struggling. The code I'm trying to change is taken from http://www.w3resource.com/csharp-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-10.php I tested the code with an array and it worked. Does anybody have any ideas how to make radix sort work in a linked list?
//abstract class
abstract class DataList
{
protected int length;
public int Length { get { return length; } }
public abstract double Head();
public abstract double Next();
public abstract void Swap(int a, int b);
public void Print(int n)
{
Console.Write("{0} ", Head());
for (int i = 1; i < n; i++)
Console.Write("{0} ", Next());
Console.WriteLine();
}
}
//linked list class
class LinkedList : DataList
{
class MyLinkedListNode
{
public MyLinkedListNode nextNode { get; set; }
public int data { get; set; }
public MyLinkedListNode(int data)
{
this.data = data;
}
public MyLinkedListNode()
{
this.data = 0;
}
}
MyLinkedListNode headNode;
MyLinkedListNode prevNode;
MyLinkedListNode currentNode;
public LinkedList(int n, int min, int max)
{
length = n;
Random rand = new Random();
headNode = new MyLinkedListNode(rand.Next(min, max));
currentNode = headNode;
for (int i = 1; i < length; i++)
{
prevNode = currentNode;
currentNode.nextNode = new MyLinkedListNode(rand.Next(min, max));
currentNode = currentNode.nextNode;
}
currentNode.nextNode = null;
}
public LinkedList()
{
headNode = new MyLinkedListNode();
currentNode = headNode;
}
public override double Head()
{
currentNode = headNode;
prevNode = null;
return currentNode.data;
}
public override double Next()
{
prevNode = currentNode;
currentNode = currentNode.nextNode;
return currentNode.data;
}
public override void Swap(int a, int b)
{
prevNode.data = a;
currentNode.data = b;
}
//my radix sort
public void radixSort()
{
int j = 0;
LinkedList tmp = new LinkedList();
for (int shift = 31; shift > -1; --shift)
{
//I try to go trough old list
MyLinkedListNode current = headNode;
while (current != null)
{
bool move = (current.data << shift) >= 0;
//I found this expression somewhere and I'm trying to use it to form a new Linked list (tmp)
if (shift == 0 ? !move : move)
;
else
{
if (tmp.headNode == null)
tmp.headNode = currentNode;
else
{
tmp.currentNode.nextNode = current;
//infinite loop happens on the commented line
//tmp.currentNode = tmp.currentNode.nextNode;
j++;
}
current = current.nextNode;
}
}
}
}
Following the C# radix sort example, you need an array of ten lists. Move nodes from the original list into the ten lists, appending a node with least signfificant digit == '0' into array_of_lists[0], '1' into array_of_list[1], and so on. After the original list is emptied, then concatenate the array of lists back into the original list and repeat for the next to least significant digit. Repeat the process until all the digits are handled.
You could use a larger base, such as base 16, where you would use an array of 16 lists. You can then select each "digit" using a shift and an and .

Circular lists in C#

I am not very experienced with C#. I am trying to build circular lists and I have done it like this:
public List<string> items = new List<string> {"one", "two", "three"};
private int index = 0;
void nextItem() {
if (index < items.Count - 1)
index += 1;
else
index = 0;
setItem();
}
void previousItem() {
if (index > 0)
index -= 1;
else
index = items.Count - 1;
setItem();
}
void Update() {
if (Input.GetKeyDown(KeyCode.RightArrow)) nextItem();
else if (Input.GetKeyDown(KeyCode.LeftArrow)) previousItem();
}
But now I am wondering: Am I reinventing the wheel? Does C# already come with a proper data structure for this?
EDIT: In case some context is needed. I have a game menu, where I display a collection of items, and I want that when I press "next" and Im at the last one, to show the first item again.
With utilization of the % (remainder) operator your code gets quite simple:
void nextItem() {
index++; // increment index
index %= items.Count; // clip index (turns to 0 if index == items.Count)
// as a one-liner:
/* index = (index + 1) % items.Count; */
setItem();
}
void previousItem() {
index--; // decrement index
if(index < 0) {
index = items.Count - 1; // clip index (sadly, % cannot be used here, because it is NOT a modulus operator)
}
// or above code as a one-liner:
/* index = (items.Count+index-1)%items.Count; */ // (credits to Matthew Watson)
setItem();
}
You cann also write your own circular list
public class CircularList<T> : List<T>, IEnumerable<T>
{
public new IEnumerator<T> GetEnumerator()
{
return new CircularEnumerator<T>(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new CircularEnumerator<T>(this);
}
}
class CircularEnumerator<T> : IEnumerator<T>
{
private readonly List<T> list;
int i = 0;
public CircularEnumerator(List<T> list){
this.list = list;
}
public T Current => list[i];
object IEnumerator.Current => this;
public void Dispose()
{
}
public bool MoveNext()
{
i = (i + 1) % list.Count;
return true;
}
public void Reset()
{
i = 0;
}
}
public class CircularList<T> : List<T>
{
private int Index;
public CircularList() : this(0) { }
public CircularList(int index)
{
if (index < 0 || index >= Count)
throw new Exception(string.Format("Index must between {0} and {1}", 0, Count));
Index = index;
}
public T Current()
{
return this[Index];
}
public T Next()
{
Index++;
Index %= Count;
return this[Index];
}
public T Previous()
{
Index--;
if (Index < 0)
Index = Count - 1;
return this[Index];
}
public void Reset()
{
Index = 0;
}
public void MoveToEnd()
{
Index = Count - 1;
}
}

Why is insert function not working?

I have written a piece of code to implement a linked list and add a new node in a position.
public class Node
{
//this is the class which creates each node.
public Node NextInstance; //this is the instance which creates the node.
public object data; // this will have the data
public Node(object data) //Constructer
{
this.data = data;
}
public Node()
{
}
}
public class LinkedList
{
Node Head; // this is for the head instance.
Node Current;
Node temp1;
// Add the method which will create a node
public void Add_Node(Node N)
{
if (Head == null)
{
//if the head is null, set the first instance to head
Head = N; // "First" = Head
Current = Head; // Set the Current to Head; Current = "First"
}
else
{
Current.NextInstance = N; // Current.NextInstance = "Second";
Current = Current.NextInstance; //Current = "Second";
}
}
public void Print_Nodes()
{
//this is the method to print the instance
temp1 = Head;
while (Head != null)
{
//just traverse
Console.WriteLine(Head.data);
Head = Head.NextInstance;
}
}
public void Insert_Node(int position, string Val)
{
Node T = new Node(Val);
Node temp;
//T.data = Val;
int k = 0;
Head = temp1;
while (Head != null)
{
k += 1;
if (k == position)
{
temp = Head;
Head = T;
Head.NextInstance = temp;
}
Head = Head.NextInstance;
}
}
}
class Program
{
static void Main(string[] args)
{
LinkedList LL = new LinkedList();
LL.Add_Node(new Node("First"));
LL.Add_Node(new Node("Second"));
LL.Add_Node(new Node("Third"));
//LL.Print_Nodes();
LL.Insert_Node(2, "Shef");
LL.Print_Nodes();
Console.ReadLine();
}
}
The code in Insert_Node isn't working correctly. Could anyone correct me please?
you shouldn't change the head node if the new node is not will be head.
public void Insert_Node(int position, string Val)
{
Node T = new Node(Val);
Node temp = Head;
int i = 0;
if (position == i)
{
T.NextInstance = Head;
Head = T;
}
else
{
while (temp != null && i < position-1)
{
temp = temp.NextInstance;
i++;
}
T.NextInstance = temp.NextInstance;
temp.NextInstance = T;
}
}

How do I correct an implicit conversion error in BST C# Code?

I wrote this code
I have these errors
Cannot implicitly convert type x.Program.TreeNode' to 'int' // on findmin
Cannot implicitly convert type x.Program.TreeNode' to 'int' // on findmax
and is my main correct or missing somethin?
and how i can count the nodes,leaves and get the hight (need only hints)
class Program
{
static void Main(string[] args)
{
BinarySearchTree t = new BinarySearchTree();
t.insert(ref t.root, 10);
t.insert(ref t.root, 5);
t.insert(ref t.root, 6);
t.insert(ref t.root, 17);
t.insert(ref t.root, 2);
t.insert(ref t.root, 3);
BinarySearchTree.print(t.root);
}
public class TreeNode
{
public int n;
public TreeNode _left;
public TreeNode _right;
public TreeNode(int n, TreeNode _left, TreeNode _right)
{
this.n = n;
this._left = _left;
this._right = _right;
}
public void DisplayNode()
{
Console.Write(n);
}
}
public class BinarySearchTree
{
public TreeNode root;
public BinarySearchTree()
{
root = null;
}
public void insert(ref TreeNode root, int x)
{
if (root == null)
{
root = new TreeNode(x, null, null);
}
else
if (x < root.n)
insert(ref root._left, x);
else
insert(ref root._right, x);
}
public int FindMin()
{
TreeNode current = root;
while (current._left != null)
current = current._left;
return current;
}
public int FindMax()
{
TreeNode current = root;
while (current._right != null)
current = current._right;
return current;
}
public TreeNode Find(int key)
{
TreeNode current = root;
while (current.n != key)
{
if (key < current.n)
current = current._left;
else
current = current._right;
if (current == null)
return null;
}
return current;
}
public void InOrder(ref TreeNode root)
{
if (root != null)
{
InOrder(ref root._left);
root.DisplayNode();
InOrder(ref root._right);
}
}
public static void print(TreeNode root)
{
if (root != null)
{
print(root._left);
Console.WriteLine(root.n.ToString());
print(root._right);
}
}
Since you need (FindMin/FindMax) to return an int, do you mean current.n?
Updated: for counting leaves and nodes, how about (as instance methods of TreeNode):
public int CountNodes()
{
int count = 1; // me!
if (_left != null) count += _left.CountNodes();
if (_right != null) count += _right.CountNodes();
return count;
}
public int CountLeaves()
{
int count = (_left == null && _right == null) ? 1 : 0;
if (_left != null) count += _left.CountLeaves();
if (_right != null) count += _right.CountLeaves();
return count;
}
If I've missed the point, let me know...
Your FindMin() and FindMax() methods are trying to return TreeNode objects but the signature says they returns ints. As it doesn't appear that the methods are used in the program, prehaps you could remove them?

Categories

Resources